return top K frequent elements
Question:
The task is to return the K most frequent elements.
What I did is to calculate the frequencies and put it in a min-heap (as we know there’s no max-heap in Python), then I need to heappop
k times.
from collections import defaultdict
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
counts = defaultdict(int)
for i in range(len(nums)):
counts[nums[i]] -= 1
counts = list(counts.items())
heapq.heapify(counts)
top_k = [heapq.heappop(counts)[0] for i in range(k)]
return top_k
Why does my code fails on topKFrequent([4,1,-1,2,-1,2,3], 2)
?
Answers:
Using collectons.Counter
would be a lot easier:
return list(dict(sorted(Counter(nums).items(), key=lambda x:x[1])).keys())[:k]
You asked why it fails. It’s failing because the heappop is returning the smallest item from counts. Counts is a tuple, so it is the smallest by the first element of the tuple, which are the nums. So you are getting back the nums, but only the unique ones because the dictionary is essentially acting like set.
You are wondering why your original code failed? Here is the close examination and the culprit:
It’s because your heapify(counts) did not get what’s your expected.
from collections import defaultdict
from typing import List
from heapq import heapify, heappop
def topKFrequent(nums: List[int], k: int) -> List[int]:
counts = defaultdict(int)
for i in range(len(nums)):
counts[nums[i]] -= 1
print(f' counts: {counts} ')
counts = list(counts.items())
print(f' list of counts: {counts} ')
heapify(counts)
print(counts)
# check this outputs, to see what you got:
for i in range(k):
x = heappop(counts)[0]
print(x)
Outputs:
list of counts: [(4, -1), (1, -1), (-1, -2), (2, -2), (3, -1)] <---
# ^^ ^^ <=== two smallest
-1
1
None
To make it works again, and follow closely your original logic/structure (but simplify further):
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
if(k == len(nums)):
return nums
dc = Counter(nums)
return heapq.nlargest(k, dc, key=dc.get)
'''
The task is to return the K most frequent elements.
What I did is to calculate the frequencies and put it in a min-heap (as we know there’s no max-heap in Python), then I need to heappop
k times.
from collections import defaultdict
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
counts = defaultdict(int)
for i in range(len(nums)):
counts[nums[i]] -= 1
counts = list(counts.items())
heapq.heapify(counts)
top_k = [heapq.heappop(counts)[0] for i in range(k)]
return top_k
Why does my code fails on topKFrequent([4,1,-1,2,-1,2,3], 2)
?
Using collectons.Counter
would be a lot easier:
return list(dict(sorted(Counter(nums).items(), key=lambda x:x[1])).keys())[:k]
You asked why it fails. It’s failing because the heappop is returning the smallest item from counts. Counts is a tuple, so it is the smallest by the first element of the tuple, which are the nums. So you are getting back the nums, but only the unique ones because the dictionary is essentially acting like set.
You are wondering why your original code failed? Here is the close examination and the culprit:
It’s because your heapify(counts) did not get what’s your expected.
from collections import defaultdict
from typing import List
from heapq import heapify, heappop
def topKFrequent(nums: List[int], k: int) -> List[int]:
counts = defaultdict(int)
for i in range(len(nums)):
counts[nums[i]] -= 1
print(f' counts: {counts} ')
counts = list(counts.items())
print(f' list of counts: {counts} ')
heapify(counts)
print(counts)
# check this outputs, to see what you got:
for i in range(k):
x = heappop(counts)[0]
print(x)
Outputs:
list of counts: [(4, -1), (1, -1), (-1, -2), (2, -2), (3, -1)] <---
# ^^ ^^ <=== two smallest
-1
1
None
To make it works again, and follow closely your original logic/structure (but simplify further):
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
if(k == len(nums)):
return nums
dc = Counter(nums)
return heapq.nlargest(k, dc, key=dc.get)
'''