leetcode347(前K个高频元素:堆排序)

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

题解(一):哈希表+数组迭代,利用哈希表存储每一个数字出现的次数,再遍历哈希表,利用数组存储频率前k高的元素(我们需要用到迭代的方法,实时更新数组中的元素)

class Solution {
    
    
    public int[] topKFrequent(int[] nums, int k) {
    
    
        HashMap<Integer,Integer>map=new HashMap<>();
        for(int x:nums){
    
    
            int temp=map.getOrDefault(x,0);
            map.put(x,temp+1);
        }
        int[]res=new int[k];
        Set<Integer>key=map.keySet();
        for(int x:key){
    
    
            int value=map.get(x);
            for(int i=0;i<res.length;i++){
    
    
                if(!map.containsKey(res[i])){
    
    
                    res[i]=x;
                    break;
            }
                else if(value>=map.get(res[i])) {
    
    
                    move(i, res, x);
                    break;
                }
            }
        }
        return res;
    }
    private void move(int i,int[]res,int x){
    
    
        for(int k=res.length-1;k>i;k--){
    
    
            res[k]=res[k-1];
        }
        res[i]=x;
    }
}

题解(二):哈希表+堆,我们可以在题解(一)的基础上进行优化,将数组换成最大堆,堆中前k个元素就是频率前k高的元素

class Solution {
    
    
    public int[] topKFrequent(int[] nums, int k) {
    
    
        HashMap<Integer,Integer>map=new HashMap<>();
        for(int x:nums){
    
    
            map.put(x,map.getOrDefault(x,0)+1);
        }
        Queue<int[]>order=new PriorityQueue<>(new Comparator<int[]>() {
    
    
            @Override
            public int compare(int[] o1, int[] o2) {
    
    
                return o2[1]-o1[1];
            }
        });
        Set<Integer>key=map.keySet();
        for(int x:key){
    
    
            order.offer(new int[]{
    
    x,map.get(x)});
        }
        int[]res=new int[k];
        for(int i=0;i<k;i++){
    
    
            res[i]= Objects.requireNonNull(order.poll())[0];
        }
            return res;   
    }
}

题解(三):快排+堆,将给定数组进行升序排列之后,就不再需要用到哈希表,直接遍历数组就可以得到每个数字的频率,再将其添加到堆中,就可以得到前k个高频元素,在对数组进行升序排列时,我们可以利用快排,来降低时间复杂度

class Solution {
    
    
    public int[] topKFrequent(int[] nums, int k) {
    
    
        quickSort(0,nums.length-1,nums);
        Queue<int[]>order=new PriorityQueue<>(new Comparator<int[]>() {
    
    
            @Override
            public int compare(int[] o1, int[] o2) {
    
    
                return o2[1]-o1[1];
            }
        });
        int len=0;
        int num=Integer.MAX_VALUE;
        for(int i=0;i<nums.length;i++){
    
    
           if(nums[i]==num)
               len++;
           else{
    
    
               if(num!=Integer.MAX_VALUE)
                   order.offer(new int[]{
    
    num,len});
               num=nums[i];
               len=1;

           }
       }
        order.offer(new int[]{
    
    (int)num,len});
        int[]res=new int[k];
        for(int i=0;i<k;i++){
    
    
            res[i]= Objects.requireNonNull(order.poll())[0];
        }
            return res;
    }
    private void quickSort(int start,int end,int[]nums){
    
    
        if(start>=end)
            return;
        int pivot=nums[start];
        int left=start;
        int right=end;
        while(right>left){
    
    
            while(nums[right]>pivot&&right>left)
                right--;
            while(nums[left]<=pivot&&right>left)
                left++;
            Switch(nums,left,right);
        }
        Switch(nums,start,left);
        quickSort(start,left-1,nums);
        quickSort(left+1,end,nums);
    }
    private void Switch(int[]nums,int x,int y){
    
    
        int temp=nums[x];
        nums[x]=nums[y];
        nums[y]=temp;
    }
}

快排的时间复杂度:O(Nlog(N))(平均),O(N^2)(最坏)
快排的空间复杂度:O(log(N))(平均),O(N)(最坏)

猜你喜欢

转载自blog.csdn.net/CY2333333/article/details/108451167