题目:
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
说明:
- 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
- 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/top-k-frequent-elements
方法一:哈希表+堆
1.利用字典(哈希表)存储数组中每个元素出现的频率;
2.用一个大小为k的最小堆存储频率大小为前k个的元素。时间复杂度为O(klogk)。
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
self.key_value = {}
for i in nums:
if i in self.key_value:
self.key_value[i] = self.key_value[i]+1
else:
self.key_value[i] = 1
self.min_heap = []
for key in self.key_value:
if k>0:
self.min_heap.append(key)
self.up_shift()
k -= 1
else:
if self.key_value[key]>self.key_value[self.min_heap[0]]:
self.min_heap[0] = key
self.down_shift()
return self.min_heap[::-1]
def up_shift(self):
child_index = len(self.min_heap)-1
while(child_index>0):
parent_index = (child_index-1)//2
if parent_index>=0 and self.key_value[self.min_heap[parent_index]]>self.key_value[self.min_heap[child_index]]:
c = self.min_heap[child_index]
self.min_heap[child_index] = self.min_heap[parent_index]
self.min_heap[parent_index] = c
child_index = parent_index
else:
break
def down_shift(self):
l = len(self.min_heap)
parent_index = 0
while(parent_index<l-1):
left_child = parent_index*2+1
right_child = left_child+1
c = self.key_value[self.min_heap[parent_index]]
index = 0
if left_child<l and c>self.key_value[self.min_heap[left_child]]:
index = left_child
c = self.key_value[self.min_heap[left_child]]
if right_child<l and c>self.key_value[self.min_heap[right_child]]:
index = right_child
c = self.key_value[self.min_heap[right_child]]
if index!=0:
c = self.min_heap[index]
self.min_heap[index] = self.min_heap[parent_index]
self.min_heap[parent_index] = c
parent_index = index
else:
break
方法二:哈希表+二分查找
哈希表统计词频,维护一个大小为k的有序列表来存储当前频率为前k个的元素,元素的替换和查找可以使用二分查找。
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
result = []
counting = {}
for i in nums:
if i in counting.keys():
counting[i]+=1
else:
counting[i]=1
if i in result:
result.remove(i)
if not result:
result.append(i)
else:
if counting[i]>=counting[result[-1]]:
result.append(i)
elif counting[i]<=counting[result[0]]:
result.insert(0, i)
else:
start = 0
end = len(result)
while(1):
index = (start+end)//2
if counting[result[index]]==counting[i]:
break
elif counting[result[index]]>counting[i]:
if counting[result[index-1]]<=counting[i]:
break
else:
end = index
else:
if counting[result[index+1]]>=counting[i]:
index = index+1
break
else:
start = index
result.insert(index, i)
if len(result)>k:
result.pop(0)
return result