Top K Frequent Elements 之 topk问题

Posted yawenw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
    }
}

 

以上是关于Top K Frequent Elements 之 topk问题的主要内容,如果未能解决你的问题,请参考以下文章

347. Top K Frequent Elements/692. Top K Frequent Words

LeetCode Top K Frequent Elements

#Leetcode# 347. Top K Frequent Elements

LeetCode 347. Top K Frequent Elements

347. Top K Frequent Elements

347. Top K Frequent Elements