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)(最坏)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值