I was trying this problem on Leetcode:
Given an integer array nums and an integer k, return the k most
frequent elements. You may return the answer in any order.
I made a dictionary of the elements in the list and incremented their count every time that number appeared again but I’m stuck on how to get the keys that match the highest values into the list that should be returned.
The code below is what I tried. The commented out are other variations of what I tried.
I googled possible ways to do it (the commented out sections are some approaches I found) but none of them are doing what I want, and I’m unsure what I’m doing wrong.
def most(nums, k):
nums_hash = {}
nums_list = []
for number in nums:
if number in nums_hash:
nums_hash[number] +=1
else:
nums_hash[number] = 1
for key, value in nums_hash:
if value >= k:
nums_list.append(key)
# for v in nums_hash.values():
# if v > k:
# nums_list.append(nums_hash.keys())
# for number in nums_hash:
# if number >= k:
# nums_list.append(number)
return nums_list
print(most([1,1,1,2,2,3], k = 2))
The error I get is
ERROR!
Traceback (most recent call last):
File "<string>", line 28, in <module>
File "<string>", line 13, in most
TypeError: cannot unpack non-iterable int object
>Solution :
This code is substantially correct:
for number in nums:
if number in nums_hash:
nums_hash[number] +=1
else:
nums_hash[number] = 1
It builds a frequency table from your input. E.g., given your sample input, you get:
{1: 3, 2: 2, 3: 1}
The problem asks for the k most frequent terms. That means you need to:
- Sort the table by frequency, and then
- Return the first
kitems
You’re not doing that, when you write:
for v in nums_hash.values():
if v > k:
nums_list.append(nums_hash.keys())
You are producing a list of numbers greater than k, which is not what the problem is asking for. You can use the frequency table to produce a list of numbers sorted by frequency:
nums_sorted = list(reversed(sorted(nums_hash, key=lambda x: nums_hash[x])))
Then you just need to return the first k elements. Putting that all together, we get:
import random
def most(nums, k):
nums_hash = {}
nums_list = []
for number in nums:
nums_hash[number] = nums_hash.get(number, 0) + 1
nums_sorted = list(reversed(sorted(nums_hash, key=lambda x: nums_hash[x])))
print("nums_hash:", nums_hash)
print("nums_sorted:", nums_sorted)
return nums_sorted[:k]
numbers = random.choices(range(10), k=30)
k = 2
print("numbers:", numbers)
print(f"{k} highest:", most(numbers, k=k))
Using your original input, the most function returns:
[1,2]
Running it as written with a random range of numbers produces something like:
numbers: [1, 0, 3, 4, 1, 4, 0, 9, 6, 6, 1, 9, 3, 8, 9, 3, 7, 8, 9, 8, 1, 3, 9, 3, 9, 7, 1, 1, 3, 4]
nums_hash: {1: 6, 0: 2, 3: 6, 4: 3, 9: 6, 6: 2, 8: 3, 7: 2}
nums_sorted: [9, 3, 1, 8, 4, 7, 6, 0]
2 highest: [9, 3]
I left a bunch of print statements in the code so you can see what the different variables look like.
Note that I didn’t pay any attention to algorithmic complexity while writing this (which is one of the constraints on the problem), so you may not be able to use it as written. It was meant to suggest a direction, not to be an acceptable solution.