代码随想录算法训练营第十三天| 239. 滑动窗口最大值,347.前 K 个高频元素.

239. 属于hard的题目,目前能力不够哈哈,直接看了carl哥的视频讲解,大差不差的理解了。附上视频的链接在此:239. 滑动窗口最大值。(自定义单调队列)

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length == 1) {
            return nums;
        }

        //res数组的长度
        int len = nums.length - k + 1;
        int[] res = new int[len];

        //自定义的单调队列
        MyQueue myQueue= new MyQueue();

        int num = 0;
        //先将前k个值加入到队列中
        for(int i=0; i<k; i++){
            myQueue.add(nums[i]);
        }

        //当前初始滑动窗口内的最大值,先加入到res中
        res[num++] = myQueue.peek();

        // 滑动窗口的移动
        for(int i=k; i<nums.length; i++){
            myQueue.poll(nums[i-k]);
            myQueue.add(nums[i]);
            res[num++] = myQueue.peek();
        }

        return res;

    }
}

class MyQueue {
    Deque<Integer> que = new LinkedList<>();

    // 只有当poll值==peek的值的时候才poll,说明这个值已经不在当前的窗口内,要去寻找下一个窗口的最大值
    public void poll(int val){
        if(!que.isEmpty() && que.peek() == val){
            que.poll();
        }
    }

    // 在push的时候需要进行比较,移除所有比val小的值
    //添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出,保证队列元素单调递减
    //比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2
    public void add(int val){
        while(!que.isEmpty() && que.getLast() < val){
            que.removeLast();
        }
        que.add(val);
    }

    //获取最大值就是队列出口的值
    public int peek(){
        return que.peek();
    }
}

 

347. 这一题呢,其实不算难,但是我没做出来。主要是因为对堆和优先队列的不熟悉,这个数据结构很少用到,一时间没想起来,想起来估计也忘记怎么用了哈哈。看了题解之后感觉还是蛮简单的,只要掌握优先队列就行了,算是复习了下数据结构和算法了。

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
        for(int num:nums){
            map.put(num,map.getOrDefault(num,0)+1);
        }

        //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
        //出现次数按从队头到队尾的顺序是从大到小排,出现次数最多的在队头(相当于大顶堆)
        //    pair1和pair2分别代表队列中的两个元素(即两个数组)。
        //    pair2[1]-pair1[1]表示比较这两个数组的第二个元素的值。
        //    如果结果为正数,意味着pair2的第二个元素比pair1的第二个元素大,因此在优先队列中,pair2应该排在pair1之前。
        //    如果结果为负数,意味着pair1的第二个元素比pair2的第二个元素大,pair1将排在pair2之前。
        //    如果结果为零,则认为这两个元素在排序时是相等的。
        PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2)->pair2[1]-pair1[1]);
        for(Map.Entry<Integer,Integer> entry:map.entrySet()){//大顶堆需要对所有元素进行排序
            pq.add(new int[]{entry.getKey(),entry.getValue()});
        }
        int[] ans = new int[k];
        for(int i=0;i<k;i++){//依次从队头弹出k个,就是出现频率前k高的元素
            ans[i] = pq.poll()[0];
        }
        return ans;
    }
}

总结: 上面这两道题都是说一刷了解思路,题目还是蛮有意思的,希望二刷再好好理解下吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值