【算法第十天7.24】滑动窗口最大值,前 K 个高频元素

链接:力扣239-滑动窗口最大值
思路:维护一个队头为窗口内最大值下标的单调队列

根据题意,i为nums下标,是要在[i - k + 1, i] 中选到最大值,只需要保证两点

1.队列头结点需要在[i - k + 1, i]范围内,不符合则要弹出

2.在k滑动窗口范围之内,队列中已有数字比将要放进去的数字要小,否则队里已有数字需要弹出

3.剩下元素都直接入队

4.从k - 1 开始,每次都可以将队头下标所对应的元素放入结果队列中

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        Deque<Integer> deque = new ArrayDeque<>();
        int n = nums.length;
        int[] res = new int[n - k + 1];
        int idx = 0;
        for(int i = 0; i < n; i++) {
            // 根据题意,i为nums下标,是要在[i - k + 1, i] 中选到最大值,只需要保证两点
            // 1.队列头结点需要在[i - k + 1, i]范围内,不符合则要弹出
            while(!deque.isEmpty() && deque.peek() < i - k + 1){
                deque.poll();
            }
            // 在k滑动窗口范围之内,队列中已有数字比将要放进去的数字要小,则队里已有数字需要弹出
            // 2.既然是单调,就要保证每次放进去的数字要比末尾的都大,否则也弹出
            while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
                deque.pollLast();
            }
            // 3、如果放入的元素小于当前的队头元素,则直接offer进去
            //此方法优于add ()方法,因为在容器的容量已满时,此方法不会引发异常,因为它会返回false。
            deque.offer(i);

            // 因为单调,当i增长到符合第一个k范围的时候,每滑动一步都将队列头节点放入结果就行了
            // 这里就解决了,前三个元素在能够依次遍历完的情况下,再进行后面的操作
            if(i >= k - 1){
                res[idx++] = nums[deque.peek()];
            }
        }
        return res;
    }
}

链接:力扣347-前 K 个高频元素
思路
1、用到了小顶堆(本质也是二叉树),根节点永远比孩子节点小;

2、先用map把数组元素以(数组元素,出现次数)的形式存起来
3、小顶堆中元素对象为数组[key,value];

4、如果小顶堆的根节点value小于即将加入的value,则poll出小顶堆的根节点,新的对象数组[key,value]入堆

5、如果小顶堆的长度还小于k,则新对象数组直接入堆

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();
        // key:元素值
        // value:出现次数
        for(int i = 0; i < nums.length; i++){
            map.put(nums[i],map.getOrDefault(nums[i],0) + 1);
            // map.put(nums[i],map.getOrDefault(num,0)+1);
        }
        // 小顶堆:排序数值为元素出现次数,也就是数组的第二个元素,所以是a[1] - b[1]
        // 堆中放的是int数组[key,value];
        PriorityQueue<int[]> pq = new PriorityQueue<>((a,b) -> a[1] - b[1]);
        for(Map.Entry<Integer,Integer> entry:map.entrySet()){
            if(pq.size() < k){
                pq.add(new int[]{entry.getKey(),entry.getValue()});
            }else{
                if(pq.peek()[1] < entry.getValue()){
                    pq.poll();
                    pq.add(new int[]{entry.getKey(),entry.getValue()});
                }
            }
        }
        int[] res = new int[k];
        for(int i = 0; i < k; i++){
            res[i] = pq.poll()[0];
        }
        return res;
    }
}

你可能感兴趣的:(算法)