def top_k(nums, k):
res = []
for i in range(k):
max_num = max(nums, key=nums.count)
res.append(max_num)
for num in nums:
if num == max_num:
nums.remove(num)
return res
이 풀이를 unit tests에 돌렸더니 한 개가 빨간불 즉, 틀렸다고 표시되었다.
정민님과 계속 고민해보다가 for num in nums
를 for num in nums[:]
로 바꾸면 된다는 것을 깨달았다. 여기서 생긴 궁금증.. num
과 nums[:]
가 무슨 차이점이 있는 걸까?
list
와 list[:]
의 차이점을 알아보기 위해 아래의 간단한 코드를 만들어 실행시켜 보았다.
nums = [1,2,3,4,5]
for num in nums:
nums.remove(num)
print('삭제값: ', num)
print('남은값: ', nums)
nums = [1,2,3,4,5]
for num in nums[:]:
nums.remove(num)
print('삭제값: ', num)
print('남은값: ', nums)
위는 코드를 실행시킨 결과이다.
for num in nums:
로 시작하는 첫 번째 for문부터 알아보자.
for문을 처음으로 돌릴 때의 num
은 1
이다. 그리고 nums.remove(num)
으로 인해 nums==[2,3,4,5]
가 된다. 그 후에 다시 돌아온 for
문은 2
를 가리키지 않고 3
을 가리키게되어 3
이 remove 된다.
왜냐하면 for a in list
는 list의 각 숫자를 기준으로 a로 뽑아내는 것이 아니라, index를 기준으로 뽑아내기 때문이다. 위의 코드와 결과창을 다시 보자. nums = [1, 2, 3, 4, 5]
의 for
문의 첫 사이클에서 인덱스 0번(1)을 remove했으므로, 그 다음 for
문 사이클에선 인덱스 1번을 remove 해야한다. 첫 사이클로 인덱스 0번인 1이 삭제되어 nums==[2,3,4,5]
이므로 그 다음에 삭제될 인덱스 1번은 2가 아닌 3이 된다. 고로 1 다음으로 삭제되는 값이 2가 아닌 3이 되는 것이다.
이제 for문이 돌아가는 방식은 알았다.
그런데 왜 두 번째 for
문은 정상적으로 모든 값이 삭제되는걸까?
왜냐하면 list[:]
는 list
가 아닌 list
의 복사본이기 때문이다.
copy_list = list[:]
라고 할 때, list
가 [1, 2, 3, 4, 5]
에서 [6, 2, 3, 4, 5]
로 바뀌어도 copy_list
는 복사본에 불과하기에 원본값의 변화를 반영하지 않아 여전히 [1, 2, 3, 4, 5]
이다.
즉, for
문에서 삭제되는 값은 nums
이지 nums
의 복사본인 nums[:]
가 아니다. 고로 for
문에 있는 nums[:]
는 for
문의 시작부터 끝까지 [1, 2, 3, 4, 5]
를 유지하므로, for
문으로 돌리며 요소의 삭제로 인해 놓치는 인덱스가 없어진다. 고로, 정상적으로 모든 값을 삭제할 수 있다.
def top_k(nums, k):
res = []
for i in range(k):
max_num = max(nums, key=nums.count)
res.append(max_num)
for num in nums[:]:
if num == max_num:
nums.remove(num)
return res
위의 풀이 중 max값에 해당하는 요소를 삭제하기 위한 for문을 list comprehension을 이용하여 줄일 수 있다.
아래 코드를 참고하자.
def top_k(nums, k):
res = []
for i in range(k):
max_num = max(nums, key=nums.count)
res.append(max_num)
nums = [j for j in nums if j not in res]
return res
def top_k(nums, k):
return sorted(set(nums), key=nums.count, reverse=True)[:k]
count
값이 큰 순으로 nums
를 나열하여 set
를 적용해, 값을 하나씩만 남겨 인덱싱으로 k개를 return하는 코드이다.
set(nums)
를 sorted
할 때 key
를 이용하여 nums.count
를 기준으로 sorted
하도록 한다.
sorted
함수는 오름차순 정렬이기에, 큰 값부터 나오도록 내림차순 하기위해 reverse=True
를 적용한다.
sorted
의 return type은 list
이므로 바로 indexing하여 return이 가능하다.