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

빠키·2020년 7월 22일
2

알고리즘 문제

목록 보기
2/10
post-thumbnail

출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges

Challenge

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

  • 구조대 : 119
  • 박준영 : 97 674 223
  • 지영석 : 11 9552 4421

전화번호부에 적힌 전화번호를 담은 배열 phone_book 이 solution 함수의 매개변수로 주어질 때, 어떤 번호가 다른 번호의 접두어인 경우가 있으면 false를 그렇지 않으면 true를 return 하도록 solution 함수를 작성해주세요

제한사항

  • phone_book의 길이는 1 이상 1,000,000 이하입니다.
  • 각 전화번호의 길이는 1 이상 20 이하입니다.

입출력 예

phone_bookreturn
["119", "97674223", "1195524421"]false
["123", "456", "789"]true
["12", "123", "1235", "567", "88"]false

입출력 예 설명
예제 #2
한 번호가 다른 번호의 접두사인 경우가 없으므로, 답은 true입니다.
예제 #3
첫 번째 전화번호, “12”가 두 번째 전화번호 “123”의 접두사입니다. 따라서 답은 false입니다.

Solution

1. On my own(1)

def solution(phone_book):
    """
    - param phone_book : 전화번호를 담은 배열 (List)
    - return : 어떤 번호가 다른 번호의 접두어인 경우 false 
              / 그렇지 않으면 true (boolen)
    """
    phone_book.sort()
    phone_book.sort(key = len)
    
    answer = True
    
    while True : 
        prefix = phone_book[0]
        phone_book = phone_book[1:]
        for phone in phone_book : 
            if prefix == phone[:len(prefix)] : 
                answer = False
                break;
        if len(phone_book) == 1 :
            break;

    return answer

풀이 방법
sort(key = len)을 통해 str의 길이에 따라 정렬한 뒤, phone_book의 첫번째를 접두사로 지정하여 나머지 전화번호의 앞자리와 비교
(※ 정확도는 100점이지만, 효율성에서 0점을 맞았다.. 선형 탐색의 단점!)

2. Best Code(1)

def solution(phoneBook):
    phoneBook = sorted(phoneBook)

    for p1, p2 in zip(phoneBook, phoneBook[1:]):
        if p2.startswith(p1):
            return False
    return True

풀이 방법
On my own과 비교하자면, ① 문자 길이 상관없이 문자열 정열. ② 접두사 비교시, 나머지 전화번호가 아닌 바로 다음 전화번호와 비교. 두가지 관점에서 매우 간단하고, 시간적으로더 효율적임.

3. Best Code(2)

def solution(phone_book):
    answer = True
    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:
                answer = False
    return answer

풀이 방법
hash를 이용한 풀이 방법인데.. 움 굳이 아이디어는 같지만 hash를 사용하지 않아도 될 것 같아서 아래와 같이 시도함.

4. On my own(2)

def solution(phone_book) :
    for phone in phone_book : 
        temp = ''
        for num in phone :
            temp += num
            if temp in phone_book and temp != phone : 
                return False
    return True

풀이 방법
아이디어는 3번 코드와 같지만, hash는 사용하지 않음. 효율성 테스트에서도 조금 더 빠름.

Lessons learned

역시 코딩테스트에서 선형 탐색은 제일 안좋은 것 같다.
Best Code 두 개 모두 아이디어가 좋아서 배울 점도 많고, 특히 3. Best Code(2)는 벤치마킹하여 새로운 코드로 다시 해볼 수 있어서 좋았다!

profile
하고 싶은 것이 많기에, 앞으로 할 수 있는 일들이 더 많은 Data Scientist

2개의 댓글

comment-user-thumbnail
2021년 3월 7일

글 잘보고 갑니다. 궁금한게 있어서 댓글 남겨요. Best Code(1)도 정렬된 phone_book을 index 0부터 끝까지 iteration을 돌면서 원하는 값을 찾는 선형 탐색이니까, 글쓴이님께서 처음 작성한 On my own(1)과의 차이점은 선형탐색을 효율적으로 하였는가 차이 아닌가요? 글쓴이님은 선형탐색을 n번 하였고, Best Code(1)은 선형탐색을 1번만 하였으니까요.

답글 달기
comment-user-thumbnail
2021년 3월 14일

이제 On my own(2)는 효율성 테스트에서 통과하지 못하네요

답글 달기