TopK问题总结

总结

一般有三种解法,排序、堆、快排思想

1.寻找第K大

描述: 给定一个整数数组a,同时给定它的大小n和要找的K(1<=K<=n),请返回第K大的数(包括重复的元素,不用去重),保证答案存在。

import java.util.*;

public class Solution {
    public int findKth(int[] a, int n, int K) {
        // write code here
        return quickSort(a,0,n-1,K);
    }
    
    public int quickSort(int[] a,int left,int right,int K){
    	//从大到小快排
        int i=left;
        int j=right;
        int pos=a[left];
        while(i<j){
            while(i<j&&a[j]<=pos){
                j--;
            }
            a[i]=a[j];
            while(i<j&&a[i]>=pos){
                i++;
            }
            a[j]=a[i];
        }
        a[i]=pos;
        
        if(K==i+1){
            return a[i];
        }else if(K<i+1){
            return quickSort(a,left,i-1,K);
        }else{
            return quickSort(a,i+1,right,K);
        }
    }
    
}

2.最小的K个数

描述: 给定一个数组,找出其中最小的K个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。如果K>数组的长度,那么返回一个空的数组

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> res=new ArrayList<>();
        if(k==0||k>input.length){
             return res;
         }else if(k==input.length){
            for(int i=0;i<input.length;i++){
                res.add(input[i]);
            }
            return res;
         }

        partitionArray(input,0,input.length-1,k);
        for(int i=0;i<input.length&&i<k;i++){
            res.add(input[i]);
        }
        return res;
    }
    
    public void partitionArray(int[] input,int left,int right,int k){
        int m=quickSort(input,left,right);
        if(k==m){
        //前k个数即为所求
            return;
        }else if(k>m){
            partitionArray(input,m+1,right,k);
        }else if(k<m){
            partitionArray(input,left,m-1,k);
        }
    }
    
    public int quickSort(int[] input,int left,int right){
    	//从小到达快排
        int pos=input[left];
        while(left<right){
            while(left<right&&input[right]>=pos){
                right--;
            }
            input[left]=input[right];
            while(left<right&&input[left]<=pos){
                left++;
            }
            input[right]=input[left];
        }
        input[left]=pos;
        return left;
    }
}

3.出现次数的TopK问题

描述: 请返回出现次数前k名的字符串和对应的次数。
返回的答案应该按字符串出现频率由高到低排序。如果不同的字符串有相同出现频率,按字典序排序。

import java.util.*;
public class Solution {
    /**
     * return topK string
     * @param strings string字符串一维数组 strings
     * @param k int整型 the k
     * @return string字符串二维数组
     */
    public String[][] topKstrings (String[] strings, int k) {
        // write code here
        Map<String, Integer> map = new HashMap<>();
        for(String s : strings){
            map.put(s, map.getOrDefault(s,0)+1);
        }
        
        //默认为最小堆,定义Node排序规则
        PriorityQueue<Node> minHeap = new PriorityQueue<>(k);
        
        for(Map.Entry<String,Integer> entrySet : map.entrySet()){
            Node node=new Node(entrySet.getKey(),entrySet.getValue());
            if(minHeap.size()<k){
                minHeap.offer(node);
            }else{
                if(minHeap.peek().compareTo(node)<0){
                    minHeap.poll();
                    minHeap.offer(node);
                }
            }
        }
        
        String[][] res=new String[k][2];
        for(int i=k-1;i>=0;i--){
            Node node=minHeap.poll();
            res[i][0]=node.name;
            res[i][1]=String.valueOf(node.count);
        }
        return res;
    }
}

class Node implements Comparable<Node>{
    String name;
    int count;
    
    public Node(String name, int count){
        this.name=name;
        this.count=count;
    }
    
    @Override
    public int compareTo(Node node){
        //count大,则交换
        if(this.count>node.count){
            return 1;
        }else if(this.count<node.count){
            return -1;
        }else{
            //字典序小,则交换到前面
            return node.name.compareTo(this.name);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值