zoukankan      html  css  js  c++  java
  • [LeetCode] 239. Sliding Window Maximum(滑动窗口的最大值)

    Description

    You are given an array of integers nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
    给定一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左端移动到最右端。你只能看见窗口内的 k 个数。滑动窗口每次向右移动一个单位。

    Return the max sliding window.
    返回每个滑动窗口的最大值。

    Examples

    Example 1

    Input: nums = [1,3,-1,-3,5,3,6,7], k = 3
    Output: [3,3,5,5,6,7]
    Explanation: 
    Window position                Max
    ---------------               -----
    [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
    

    Example 2

    Input: nums = [1], k = 1
    Output: [1]
    

    Example 3

    Input: nums = [1], k = 1
    Output: [1]
    

    Example 4

    Input: nums = [9,11], k = 2
    Output: [11]
    

    Example 5

    Input: nums = [4,-2], k = 2
    Output: [4]
    

    Constraints

    • 1 <= nums.length <= 1e5
    • -1e4 <= nums[i] <= 1e4
    • 1 <= k <= nums.length

    Hints

    1. How about using a data structure such as deque (double-ended queue)?
      试试使用像双向队列这样的数据结构?

    2. The queue size need not be the same as the window's size.
      队列的大小不需要和窗口大小相等。

    3. Remove redundant elements and the queue should store only elements that need to be considered.
      移除多余的元素,队列里只保存需要被考虑的元素。

    Solution

    以下解法来自我的一本算法书:

    题目的提示告诉我们使用双端队列,为什么不用普通队列?因为双端队列可以从队尾添加,删除元素。我们希望队首永远是窗口的最大值,那自然只能在入队的时候队元素作筛选了。需要注意的是,我们在双端队列里存的是元素下标而非元素本身,这是为了方便清理失效的最大值。队列的维护规则如下:

    • 插入规则:队列为空时直接插入,否则比较队尾对应的元素与当前元素,若当前元素更大,则不断从队尾弹出元素,直到当前元素小于队尾对应元素,然后将该元素的下标入队。
    • 取最大值的规则:若队首元素超出窗口范围,则弹出该元素,否则,队首对应元素即为当前窗口的最大值。

    代码如下:

    class Solution {
        fun maxSlidingWindow(nums: IntArray, k: Int): IntArray {
            if (k == 1) {
                return nums
            }
            if (k >= nums.size) {
                return intArrayOf(nums.max()!!)
            }
    
            val maxIndices: Deque<Int> = ArrayDeque()
            val result = arrayListOf<Int>()
    
            for (i in nums.indices) {
                while (maxIndices.isNotEmpty() && nums[maxIndices.peekLast()] <= nums[i]) {
                    maxIndices.pollLast()
                }
                maxIndices.offerLast(i)
                if (maxIndices.peekFirst() == i - k) {
                    maxIndices.pollFirst()
                }
                if (i >= k - 1) {
                    result.add(nums[maxIndices.peekFirst()])
                }
            }
    
            return result.toIntArray()
        }
    }
    
  • 相关阅读:
    Mysql数据库的使用总结之ERROR 1146 (42S02)
    正在连接 cn.archive.ubuntu.com (91.189.91.39)] [正在连接 security.ubuntu.co.....问题的解决
    如何设定用F12进入bios
    thinkphp volist用法
    array_flip() 函数,一维数组,键名和键值交换..
    shell 备份数据库
    shell 备份数据库,并移动到备份数据库
    shell脚本实现取当前时间
    获取某日是否是工作日
    showModalDialog is not defined 的解决方案
  • 原文地址:https://www.cnblogs.com/zhongju/p/14166576.html
Copyright © 2011-2022 走看看