본문 바로가기

B/Coding Test

[프로그래머스] 해시 - 전화번호 목록

https://programmers.co.kr/learn/courses/30/lessons/42577

 

코딩테스트 연습 - 전화번호 목록

전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다. 전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다. 구조

programmers.co.kr

 

 

 

[내 풀이]

 

첫번째 풀이)

 

 

접두사의 의미를 모르고 맨 처음에 not in 과 in 을 이용해서 반복문을 돌려서 자꾸 에러가 났다.

특히 문자열이 박힌 list를 굳이 int를 만들어서 sort하려는 행위가 문제를 제대로 이해한게 아니라는 생각이 든다.

바로 string값에서 sort를 해주고 앞뒤만 비교해주는 것이 왜 정답이 될 수 있는지에 대해 생각을 못했던 것 같다.

수능수학과 같은 느낌이다. 코테 또한 문제를 잘 읽고 예시도 주니까 검증까지 생각하면서 코드 짜자.

 

두번째 풀이)

def solution(phone_book):
    
    answer = True
    
    if len(phone_book)==1:
        return answer
    else:
        temp = sorted(phone_book)
        
        while len(temp)>1:
            head = temp.pop(0)
            for i in range(len(temp)):
                if head == temp[i][:len(head)]:
                    answer = False
                    break
        
        return answer

 

세번째 풀이)

def solution(phone_book):
    length = len(phone_book)
    
    phone_book.sort()
    for i in range(length-1):
        suffix = phone_book[i]
        for number in phone_book[(i+1):]:
            if number[:len(suffix)] == suffix:
                return False
    return True

 

두 풀이 모두 효율성 측면에서 걸렸다.

 

수정 풀이)

def solution(phone_book):
    phone_book.sort()
    for a in range(len(phone_book)-1):
        if phone_book[a] in phone_book[a+1] :
            return False
    return True

테케 13에서 걸림.

3, 23 과 같은 경우

3이 23에 포함되기 때문에 넘어가지만, 실제로 접두어는 아니기 때문에 문제 정답이 될 수 없음.

 

나 같은 경우는 오히려, 12, 384, 1249 과 같이 한 타임 뛰어있는 들어있으면 못잡지 않나?

 

sort의 결과물에 대한 이해도 부족

아스키 코드로 문자열의 크기가 아니라 맨 앞자리부터 소팅을 시작하기 때문에

위와 같은 리스트가 만들어 질리는 없음.

 

def solution(phone_book):
    phone_book.sort()
    for a in range(len(phone_book)-1):
        if phone_book[a] == phone_book[a+1][:len(phone_book[a])] :
            return False
    return True

다음과 같이 in을 쓰지말고, 슬라이싱을 해줘서 같다로 조건문 걸어주면 통과

 

[해시를 이용한 풀이]

def solution(phone_book):
    hash_map = {}
    for phone_number in phone_book:
        hash_map[phone_number] = 1
    for phone_number in phone_book:
        temp = ""
        for number in phone_number:
            temp += number
            if temp in hash_map and temp != phone_number:
                return False
    return True

가장 문제출제의도대로 잘 푼듯.

해시도 해시지만 temp에 number 더해가면서 접두사 파악해주는 의도도 창의적이었다.

 

 

[참고1]

zipstartswith이라는 내장함수를 이용해서 굉장히 깔끔하게 짠 것 같다.

 

[참고2]

def solution(phone_book):
    for i in range(len(phone_book)):
        pivot = phone_book[i] 
        for j in range(i+1, len(phone_book)):
            strlen = min(len(pivot), len(phone_book[j]))
            if pivot[:strlen] == phone_book[j][:strlen]: 
                return False 
            return True

댓글에 있는 코드인데 이것도 이중반복문을 이용해서 읽기 편한 것 같다.

 

시간복잡도 측면으로 봤을때 앞선 코드들보다 좋지 못하다.

자료구조나 알고리즘 측면으로 시간복잡도를 줄일 수도 있겠지만,

문제를 어떻게 최소한의 리소스를 들여서 해결할지, 문제를 해결하는 아이디어 측면에서도 시간복잡도를 줄일 수도 있겠다는 생각이 들었다.