刷题第13天 | 239. 滑动窗口最大值、347.前 K 个高频元素

239. Sliding Window Maximum

题目链接:239. 滑动窗口最大值
思路链接:代码随想录栈与队列

思路

构造一个自己的队列。这个队列有三个特性:

  1. push时,从已有队列的last从last到first开始遍历,如果小于要push的值,则将last值remove;如果队列为空或者大于要push的值,则在队列末尾push
  2. pop时,如果队列的first与要pop的值相等,那么就将first remove。
  3. peek时return 队列first值
    构造完以后,首先push数组中前k个值。然后从第k+1个值开始,首先pop掉滑动窗口前一个元素,然后在push。然后把peek返回的值加到result数组里。

心路历程

这道题有点复杂,看了视频文章代码后,自己实现也调试了好久,二刷时要巩固。

Code

import java.util.ArrayDeque;

class MyDeque {
    
    Deque<Integer> deq = new ArrayDeque<>();
    
    public void push(int num) {
        // 注意这里要从小到大删,即从右往左删,否则会漏删
        while (!deq.isEmpty() && deq.getLast() < num) {
            // int deqPeek = deq.peek();
            deq.removeLast();
        }
        deq.addLast(num);
    }
    
    public void pop(int num) {
        // int deqPeek = deq.peek();
        if (!deq.isEmpty() && deq.peek() == num) {
            deq.removeFirst();
        }
    }
    
    public int peek() {
        return deq.getFirst();
    }
    
    public int size() {
        return deq.size();
    }
}

class Solution {
    // 单调队列法 Runtime: O(n); 空间复杂度:O(k)
    public int[] maxSlidingWindow(int[] nums, int k) {
        // 初始化自定义deque以及result
        MyDeque deq = new MyDeque();
        int[] result = new int[nums.length - k + 1];
        // 先将数组中前k个元素push进自定义deque
        for (int i = 0; i < k; i++) {
            deq.push(nums[i]);
            result[0] = deq.peek();
        }
        // 滑动窗口移动,从第k个位置开始
        for (int i = k; i < nums.length; i++) {
            // result[i - k] = deq.peek();
            deq.pop(nums[i - k]);
            deq.push(nums[i]);
            // deq.pop(nums[i - k]);
            result[i - k + 1] = deq.peek();
        }
        return result;
    }
}

347. Top K Frequent Elements

题目链接:347.前 K 个高频元素
思路链接:代码随想录栈与队列-前 K 个高频元素

思路

这道题思路比较简单,就是遍历数组,用map记录下每个key出现的次数(value),然后再用堆的数据结构来排序,大小顶堆都可以使用,从堆里poll掉k个元素就可以了。小顶堆比较快,大顶推无非就是稍微改一下Comparator和遍历的size就行。

心路历程

实现也花了一些时间,主要是Comparator有点忘了,去研究了一下,有时候得复习一下java的语法。

Code

class MyComparator implements Comparator<int[]> {
    public int compare(int[] int1, int[] int2)
    {
        return int1[1] - int2[1];
    }
}

class Solution {
    // 小顶堆
    // 时间复杂度:O(nlogk)
	// 空间复杂度:O(n)
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        MyComparator cmp = new MyComparator();
        for (int i : nums) {
            map.put(i, map.getOrDefault(i, 0) + 1);
        }
        PriorityQueue<int[]> pq = new PriorityQueue<>(cmp);
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            if (pq.size() < k) {
                pq.add(new int[]{entry.getKey(), entry.getValue()});
            } else {
                pq.add(new int[]{entry.getKey(), entry.getValue()});
                pq.poll();
            }
        }
        int[] result = new int[k];
        for (int i = k - 1; i >= 0; i--) {
            result[i] = pq.poll()[0];
        }
        return result;
    }
}

栈与队列总结

链接: 总结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值