【KOKO-代码随想录算法训练营Day13 | 239|347 | 】

KOKO-代码随想录算法训练营Day13 | 239|347 |



一、239. 滑动窗口最大值

1.题目

https://leetcode.cn/problems/sliding-window-maximum/

2.代码

public int[] maxSlidingWindow(int[] nums, int k) {
        int[] res=new int[nums.length-k+1]; //最终数组的长度
        int index=0;
        Deque<Integer> que=new ArrayDeque<>();
        for (int i = 0; i < nums.length; i++) {
            // 模拟滑动窗口的过程,弹出一个,压进来一个,如果队头是和nums[i]一样,队头就该被弹出,不一样,说明曾经的队头被弹出过了
            if(i>k-1&&que.peek()==nums[i-k]){
                que.poll();  //1,-3,-1,3
            }
            while (!que.isEmpty()&&nums[i]>que.peekLast()){
                que.pollLast();//添加进来的元素比上一个大,则将其之前的元素从后面都出
            }
            que.offer(nums[i]);//加入从队头加入
            if(i>=k-1){
                res[index++]=que.peek();
            }
        }
        return res;
    }

3.总结

这个题很有意思,最重要的是要知道什么时候从队列头部把元素移出去,模拟出一个,进一个的窗口过程。
在队列保证队头元素是最大的,其他元素没有current元素大时,应该从队尾弹出。
在将current元素压入,
只有在i>k-1时,才进行弹出队头操作,比较的是nums[i-k]和队头元素的大小。
该题不进行优先级队列:
滑动窗口是移动的,队头的元素是要弹出的,大顶堆只能弹出最大值的元素。

二、 347.前 K 个高频元素

1.题目

https://leetcode.cn/problems/top-k-frequent-elements/

2.代码

 Map<Integer,Integer> map=new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i],map.getOrDefault(nums[i],0)+1);//频率的统计
        }
        //定义小顶堆
        PriorityQueue<int[]> priorityQueue=new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1]-o2[1];//按频率排大小
            }
        });
        for (Map.Entry<Integer,Integer> entry:map.entrySet()) {
            if(priorityQueue.size()<k){
                priorityQueue.add(new int[]{entry.getKey(),entry.getValue()});
            }else {
                if(entry.getValue()>priorityQueue.peek()[1]){
                    priorityQueue.poll();//如果后面有元素比堆大,则放到小顶堆里作为替换
                    priorityQueue.add(new int[]{entry.getKey(),entry.getValue()});//只存了前k个
                }
            }
        }
        int[] res=new int[k];
        for (int i = 0; i < k; i++) {
            res[i]=priorityQueue.poll()[0];
        }
        return res;

3.总结

使用优先级队列,小顶堆,来保存前k个高频词汇,一旦发现有频率比队列头部大时,应将小的弹出,在压入当前值,保持小队顶一直是前k个高频词汇,这样只用比前k个即可。
令,注意小顶堆的排序,

 PriorityQueue<int[]> priorityQueue=new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[1]-o2[1];//按频率排大小
            }
        });

Map排序使用List把map.entrySet装进去后用Collections进行排序

List<Map.Entry<Integer,Integer>> list=new ArrayList<>(map.entrySet());//entryset转成list,用Collection比较大小
       Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {
           @Override
           public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
               return o2.getValue()-o1.getValue();
           }
       }); 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值