【从零开始刷leetcode-11】239. 滑动窗口最大值

题目

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104
  • 1 <= k <= nums.length

解法

单调队列法

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (k == 1) return nums;
        int[] result = new int[nums.length - k + 1];
        int index = 0;
        Deque<Integer> sortDeque = new LinkedList<Integer>();
        for (int i = 0; i < k; i++) {
            if (sortDeque.isEmpty()) {
                sortDeque.offerLast(nums[i]);
            } else if (nums[i] <= sortDeque.peekFirst()) {
                // 小于队头元素,从队尾开始放入
                while (nums[i] > sortDeque.peekLast()) 
                    sortDeque.pollLast();
                sortDeque.offerLast(nums[i]);
            } else {
                while (!sortDeque.isEmpty())
                    sortDeque.pollFirst();
                sortDeque.offerFirst(nums[i]);
            }
        }
        result[index++] = sortDeque.peekFirst();
        int left = 0;
        for (left = 0; left < nums.length - k; left++) {
            int right = left + k;
            if (nums[left] == sortDeque.peekFirst()) {
                sortDeque.pollFirst();
            }
            if (nums[right] <= sortDeque.peekFirst()) {
                // 小于队头元素,从队尾开始放入
                while (nums[right] > sortDeque.peekLast()) 
                    sortDeque.pollLast();
                sortDeque.offerLast(nums[right]);
            } else {
                while (!sortDeque.isEmpty())
                    sortDeque.pollFirst();
                sortDeque.offerFirst(nums[right]);
            }
            result[index++] = sortDeque.peekFirst();
        }
        return result;

    }
}

优化

发现如果新加入的元素比队头元素(队列最大值)大的话,同样可以从队尾删除元素直至队列为空。

这样就节省了判断操作,而且代码更加简洁。

2. 用两个指针代替 for循环,增强可读性

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        // 只关注最大值,用单调队列
        // 加入新的以后,旧的且比新元素小的可以直接出对
        if (k == 1) return nums;
        int[] result = new int[nums.length - k + 1];
        int index = 0;
        // 1. 单调队列
        Deque<Integer> sortQueue = new ArrayDeque<>();
        // 2. 将前 k 个元素入队
        for (int i = 0; i < k; i++) {
            while (!sortQueue.isEmpty() && nums[i] > sortQueue.peekLast()) {
                sortQueue.pollLast();
            }
            sortQueue.offerLast(nums[i]);
        }
        // 3. 移动窗口 left是要出窗口的,right是要进窗口的
        int left = 0, right = k;
        while (right < nums.length) {
            // 移动窗口前记录当前最大值
            result[index++] = sortQueue.peekFirst();
            // left 出窗口
            if (sortQueue.peekFirst() == nums[left]) 
                sortQueue.pollFirst();
            // right 入窗口
            while (!sortQueue.isEmpty() && nums[right] > sortQueue.peekLast()) 
                sortQueue.pollLast();
            sortQueue.offerLast(nums[right]);
            left++;
            right++;
        }
        result[index++] = sortQueue.peekFirst();
        return result;
    }
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇