Top K Frequent Elements 之 topk问题
topk问题是一个十分经典的问题,解决该问题主要有两种思路。
第一种是利用 堆 结构,讲解:https://www.cnblogs.com/chengxiao/p/6129630.html
第二种是利用 快速排序
先回顾一下实现堆结构的代码:
package LCtest.com; import java.util.Arrays; public class HeapSort { public static void main(String[] args) { int[] nums = {5, 8, 6}; heapSort(nums); System.out.println(Arrays.toString(nums)); } public static void heapSort(int[] nums){ for(int i = nums.length/2-1; i >= 0; i--){ adjustHeap(nums, i, nums.length); } for(int j = nums.length-1; j > 0; j--){ swap(nums, 0, j); adjustHeap(nums, 0, j); } } public static void adjustHeap(int[] nums, int i, int length){ int temp = nums[i]; for(int k = 2*i+1; k < length; k = 2*k+1){ if(k+1 < length && nums[k] < nums[k+1]) k++; if(nums[k] > temp){ nums[i] = nums[k]; i = k; }else { break; } } nums[i] = temp; } public static void swap(int[] nums, int i, int j){ int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } }
本题用了PriorityQueue实现了最小堆:
class Solution { Map<Integer, Integer> count; public int[] topKFrequent(int[] nums, int k) { count = new HashMap<>(); for(int num: nums){ count.put(num, count.getOrDefault(num, 0)+1); } PriorityQueue<Integer> minheap = new PriorityQueue<>(new Comparator<Integer>(){ @Override public int compare(Integer o1, Integer o2){ return count.get(o1)-count.get(o2); } }); for(int num: count.keySet()){ minheap.add(num); if(minheap.size() > k) minheap.remove(); } int[] res = new int[k]; for(int i = k-1; i >= 0; i--){ res[i] = minheap.remove(); } return res; } }
回顾快速排序实现的代码:
package LCtest.com; import java.util.Arrays; public class QuickSort { public static void main(String[] args){ int[] nums = {5, 8, 6}; quickSort(nums, 0, nums.length-1); System.out.println(Arrays.toString(nums)); } public static void quickSort(int[] nums, int left, int right){ if(left > right) return; int mid = partition(nums, left, right); quickSort(nums, left, mid-1); quickSort(nums, mid+1, right); } public static int partition(int[] nums, int low, int high){ int temp = nums[low]; while(low < high){ while(low < high && nums[high] >= temp) high--; nums[low] = nums[high]; while (low < high && nums[low] <= temp) low++; nums[high] = nums[low]; } nums[low] = temp; return low; } public static void swap(int[] nums, int low, int high){ int temp = nums[low]; nums[low] = nums[high]; nums[high] = temp; } }
本题用快速排序求解的代码:
class Solution { int[] unique; Map<Integer, Integer> count; public int[] topKFrequent(int[] nums, int k) { count = new HashMap<>(); for(int num: nums){ count.put(num, count.getOrDefault(num, 0)+1); } int n = count.size(); unique = new int[n]; int i = 0; for(int num: count.keySet()){ unique[i] = num; i++; } sort(0, n-1, n-k); return Arrays.copyOfRange(unique, n-k, n); } public void sort(int left, int right, int loc){ if(left > right) return; int mid = partition(left, right); if(mid == loc) return; else if(mid > loc){ sort(left,mid-1, loc); } else{ sort(mid+1, right, loc); } } public int partition(int low, int high){ int pivot = count.get(unique[low]); int pu = unique[low]; while(low < high){ while(low < high && pivot <= count.get(unique[high])) high--; unique[low] = unique[high]; while(low < high && pivot >= count.get(unique[low])) low++; unique[high] = unique[low]; } unique[low] = pu; return low; } }