def solution(phone_book):
answer = True
phone_book.sort()
for i in range(0, len(phone_book) - 1):
if(phone_book[i] == phone_book[i+1][0:len(phone_book[i])]):
answer = False
break
return answer
기본적인 풀이 방법은 받은 phone_book을 정렬하고, 인접한 값끼리 서로 비교하면서 시간복잡도 N만에 푸는 방법이다. 풀이 방법은 그리 어렵지 않은데, 생각해내기 어려웠던 이유는 다음과 같다.
정렬 방법은 list.sort() 와 sorted(list) 가 있는데, 둘의 가장 큰 차이는 원본 리스트에 영향을 주는가? 이다.
a = [1, 2, 3]
a.sort(key=lambda x: x, reverse=True)
print(a)
>>> [3, 2, 1]
list.sort()는 원본 리스트 자체를 소팅한다. sort 내부 인자로 key 와 reverse를 줄 수 있다. key는 어떤 것을 기준으로 오름차순 할 것인지 정할 수 있고, 이 때 x: 기준 을 넣으면 된다. 기준에는 지금 예와는 맞지 않지만 (x[0], x[1]) 이런식으로 우선순위에 따라 여러 인자를 줄 수도 있다. reverse는 True로 설정할 경우 내림차순으로 변경된다.
a = [1, 2, 3]
b = sorted(a, key=lambda x: x, reverse=True)
print(a)
>>> [1, 2, 3]
print(b)
>>> [3, 2, 1]
sorted(list)는 원본 리스트에 영향을 주지 않는다. 위의 결과처럼 원본인 a리스트는 변하지 않음을 알 수 있다. 나머지 인자들은 list.sort()와 같다.
def solution(phoneBook):
phoneBook = sorted(phoneBook)
for p1, p2 in zip(phoneBook, phoneBook[1:]):
if p2.startswith(p1):
return False
return True
여기서는 zip함수를 사용했다. 파이썬으로 문제를 풀 때마다 편리한 함수가 하나씩은 꼭 등장하는 것 같다.
zip 함수는 그룹의 데이터를 서로 엮어주는 파이썬의 내장 함수이다. zip() 함수는 여러 개의 순회 가능한(iterable) 객체를 인자로 받고, 각 객체가 담고 있는 원소를 튜플의 형태로 차례로 접근할 수 있는 반복자(iterator)를 반환한다.
phoneBook = ["119", "97674223", "1195524421"]
print(zip(phoneBook, phoneBook[1:]))
>>> <zip object at 0x000001E4E29B9208>
phoneBook = ["119", "97674223", "1195524421"]
for p1 ,p2 in zip(phoneBook, phoneBook[1:]):
print(p1, p2)
>>> 119 97674223
>>> 97674223 1195524421
이렇게 보면 좀 더 쉬운데, zip 자체를 print했을 때는 이터레이터 객체가 반환되는 걸 알 수 있다. 그에 반해 해당 이터레이터를 통해 순회한 인자들을 print했을 때에는 값이 나온다. 여기서는 소팅을 안해주었지만, 문제 풀이에서는 문자열을 소팅한 이후 startswith 함수를 통해 접두어인지 아닌지 판별하고 있다. startswith 함수의 인자로는 튜플 또는 스트링 값이 올 수 있다.