原题地址

0101.png

本题有多种方法,并且由于Python语言的特性,也有多种实现方式。

不过不外乎用哈希表+快排/堆排的方式来实现。

方法一 sorted()函数

sorted()函数内部实现为timsort

关于timsort

哈希表用字典形式存储,统计每个数字出现的个数。

  1. def topKFrequent(self, nums: List[int], k: int) -> List[int]:
  2. nums_dic = dict() # 哈希表,存储的是数字以及出现的次数
  3. for num in nums:
  4. if num not in nums_dic:
  5. nums_dic[num] = 1
  6. else:
  7. nums_dic[num] += 1
  8. # 将其排序,得到[(num1, count1), (num2, count2), ...]形式的列表
  9. nums_list = sorted(nums_dic.items(), key=lambda x:x[1],reverse=True)
  10. rel = []
  11. for i in range(k):
  12. rel.append(nums_list[i][0])
  13. return rel

上述哈希表的实现可以用collection.Counter()函数自动得到

  1. def topKFrequent(self, nums: List[int], k: int) -> List[int]:
  2. nums_dic = collections.Counter(nums)
  3. # 将其排序,得到[(num1, count1), (num2, count2), ...]形式的列表
  4. nums_list = sorted(nums_dic.items(), key=lambda x:x[1],reverse=True)
  5. rel = []
  6. for i in range(k):
  7. rel.append(nums_list[i][0])
  8. return rel

方法二 most_common()函数

用python自带函数most_common()自动排序,并取前k个

注:most_common()内部实现是用的堆排序

  1. def topKFrequent(self, nums: List[int], k: int) -> List[int]:
  2. nums_dic = collections.Counter(nums)
  3. return [item[0] for item in nums_dic.most_common(k)]

方法三 快速排序(快速选择)

因为题目要求选出出现次数最多的k个,但是不需要按出现次数从大到小排列,所以我们可以用快速排序的思路,只要排好第k个元素,那么它前面的元素都是比它大的,它后面的都是比它小的,返回前k个,完毕。

此解法与215题解法几乎一致

215.数组中的第K个最大元素

  1. def topKFrequent(self, nums: List[int], k: int) -> List[int]:
  2. def Partition(low, high):
  3. temp = nums_list[low]
  4. pivlot = nums_list[low][1]
  5. while low < high:
  6. while low < high and nums_list[high][1] <= pivlot:
  7. high -= 1
  8. nums_list[low] = nums_list[high]
  9. while low < high and nums_list[low][1] >= pivlot:
  10. low += 1
  11. nums_list[high] = nums_list[low]
  12. nums_list[low] = temp
  13. return low
  14. def quickSort(low, high): # 对数组排序,找到第k大的数
  15. if low < high:
  16. pivlotpos = Partition(low, high)
  17. if pivlotpos == k:
  18. return None
  19. elif pivlotpos > k:
  20. quickSort(low, pivlotpos-1)
  21. else:
  22. quickSort(pivlotpos+1, high)
  23. nums_dic = collections.Counter(nums)
  24. nums_list = [(num, freq) for num, freq in nums_dic.items()]
  25. low, high = 0, len(nums_list)-1
  26. k -= 1 # 表示要寻找排序后下标为k的那个数
  27. quickSort(low, high)
  28. return [item[0] for item in nums_list[:k+1]]

c++版

  1. class Solution {
  2. public:
  3. int quickSort(vector<pair<int, int>>& v, int low, int high){
  4. int guard = v[low].second;
  5. pair<int, int> t = v[low];
  6. while(low < high) {
  7. while(low < high && v[high].second < guard) high--;
  8. v[low] = v[high];
  9. while(low < high && v[low].second >= guard) low++;
  10. v[high] = v[low];
  11. }
  12. v[low] = t;
  13. return low;
  14. }
  15. void mySort(vector<pair<int, int>>& v, int start, int end, int k){
  16. int pivotPos = quickSort(v, start, end);
  17. if(pivotPos == k-1) return;
  18. else if(pivotPos > k-1) mySort(v, start, pivotPos-1, k);
  19. else mySort(v, pivotPos+1, end, k);
  20. }
  21. vector<int> topKFrequent(vector<int>& nums, int k) {
  22. map<int, int> m;
  23. for(auto num : nums){
  24. m[num]++;
  25. }
  26. vector<pair<int, int> > v(m.begin(), m.end());
  27. mySort(v, 0, v.size()-1, k);
  28. vector<int> ans;
  29. for(int i=0; i<k; i++)
  30. ans.push_back(v[i].first);
  31. return ans;
  32. }
  33. };