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)?

Asked By: greenButMellow

||

Answers:

Using collectons.Counter would be a lot easier:

return list(dict(sorted(Counter(nums).items(), key=lambda x:x[1])).keys())[:k]
Answered By: The Thonnu

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.

Answered By: dsagman

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)
       
        '''
Answered By: Daniel Hao
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.