코딩 테스트/프로그래머스

[Python] 프로그래머스 전화번호 목록

위시리 2024. 10. 8. 00:46

알고리즘 고득점 kit - 해시 - lv 2


문제분석

  • 한 번호가 다른 번호의 접두어인가
  • return
  • 접두어인 경우 : false
  • 접두어가 아닌 경우 : true

 

코드 설계

  • 서로가 접두사인지 확인해야함
  • phone_book에서 순서대로 비교할 문자열 빼기 (key)
  • 해당 문자열이 접두사로 있으면 해당 key에 대한 value ++
  • 전체 해시에서 value가 0이 아닌 key가 있다면 answer = false

 

정답 코드

실패..

 

다른 사람 코드 1 - 해시

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
  1. 초기 변수 설정 : 기본적으로 접두사 관계가 없다고 가정 나중에 접두사 관계가 발견되면 answer = False
  2. hash_map = {}로 전화번호를 저장할 해시 맵(딕셔너리) 생성
  3. 해시 맵에 전화번호 저장 : 첫 번째 for문을 통해 phone_book에 있는 모든 전화번호를 hash_map에 저장. 이 때, 각 전화번호를 키로 사용하고 값으로는 1 저장. 이 과정을 통해 각 전화번호가 해시 맵에 저장됨.
  4. 접두사 여부 확인 : 두 번째 for문은 다시 phone_book 리스트를 순회하면서, 각 전화번호에 대해 접두사 여부를 확인. temp라는 빈 문자열을 만들고, 그 전화번호의 각 숫자를 하나씩 더하면서 점진적으로 접두사를 만들어냄
  5. 각 단계에서 temp가 해시 맵에 존재하고, 그 값이 현재 확인 중인 전화번호(phone_number)와 동일하지 않다면, 접두사 관계가 있다는 의미 → answer를 False로 설정하고, 더 이상 확인할 필요 없이 종료
  6. 결과 반환

 

다른 사람 코드 2 - sort

def solution(phone_book):
    answer = True
    phone_book.sort()
    for i in range(len(phone_book)-1):
        if len(phone_book[i]) < len(phone_book[i+1]):
            if phone_book[i + 1][:len(phone_book[i])] == phone_book[i]:
                answer = False
                break
    return answer
  • 만약에 어떤 번호가 다른 번호의 접두어라면 이 둘은 정렬했을 때 앞뒤에 위치하게 된다.
    예를 들어 ["1235", "123", "12348", "012"]을 입력으로 받으면, sorted(["1235", "123", "12348", "012"])는 ["012", "123", "12348", "1235"]가 된다.
  • 따라서 phone_book을 정렬하고 for문을 이용해 phone_book[i]과 phone_book[i+1] 값을 비교했다.
    첫번째 if문에서 i와 i+1의 길이를 비교한 것은 바로 아래의 if문에서 index가 out of range가 되는 것을 피하기 위함이다.
  • 효율성 테스트: ~105.76ms / 30.7MB

 

다른 사람 코드 3 - startswitch & zip

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

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

 

  • zip
print(list(zip([1,2,3], (4,5,6), "abcd")))
### [[1, 4, 'a'], [2, 5, 'b'], [3, 6, 'c']]
  • startswitch : 꽤 직관적인 함수로 p2가 p1으로 시작되면 True 아니면 False를 반환
print("dfagd".startswith("abcd"))
print("abcde".startswith("abcd"))
### False
### True