辛辣天塞!滑动窗口之【和的最大值】&【最大值集合】

简介: 本篇带来两道经典的关于滑动窗口的算法题,有兴趣可在控制台跑一跑~

image.png

本篇带来两道经典的关于滑动窗口的算法题,有兴趣可在控制台跑一跑~


求和的最大值



题目来源:上一篇掘文《温故知新 —— Sliding Window》


比如给定如下数组:[ 5, 7, 1, 4, 3, 6, 2, 9, 2 ],求出 5 个连续元素的最大和是多少?

[5, 7, 1, 4, 3] 是第一组 5 个连续元素,求和是 20[7, 1, 4, 3, 6] 是第二组 5 个连续元素,求和是 21......这样一直进行下去,最终对比发现 5 个连续元素的最大和是 24,由 [4, 3, 6, 2, 9] 组成;


这里给出本瓜的另一种写法,仅供参考:


var maxSlidingWindow = function(nums, k) {
   const sum = function (arr) {
        return arr.reduce(function(prev, curr, idx, arr){
            return prev + curr;
        });
    };
    let slidingWindow=nums.slice(0,k)
    let newSlidingWindow=[]
    let maxVal;
    for(let i=k;i<nums.length;i++){
        newSlidingWindow=slidingWindow.slice(1).concat(nums[i])
        maxVal=Math.max(sum(slidingWindow),sum(newSlidingWindow))
        slidingWindow = newSlidingWindow
    }
    return maxVal
};
const nums= [ 5, 7, 1, 4, 3, 6, 2, 9, 2 ]
const k=5
maxSlidingWindow(nums,k) // 24


求最大值集合



题目来源:leetcode-239 (复杂)

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

返回滑动窗口中的最大值。

输入: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


本题在力扣中,难度被标为:复杂,这复杂吗?

  1. 写一个函数来判断数组中最大的数;
  2. 初始化窗口,求最大值保存;
  3. 滑动窗口,再求最大值保存;
  4. 滑动直至完毕;


本瓜题解:

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var maxSlidingWindow = function(nums, k) {
  if(k===1) return nums; // 特殊情况
  let slidingWindow = nums.slice(0,k)
  let newSlidingWindow = []
  let resArr = []
  resArr.push(Math.max(...slidingWindow))
  for(let i=k;i<nums.length;i++){
      newSlidingWindow = slidingWindow.slice(1).concat(nums[i])
      resArr.push(Math.max(...newSlidingWindow))
      slidingWindow = newSlidingWindow
  }
  return resArr
};


结果,当数组长度为 10 w 时,报错 超出时间限制

噢!用 Math.max() 来每次从窗口找最大值,时间复杂度是 O(n * k),仍然很大;

窗口固定,求最大值集合 在根本上是 单调队列 的问题!

本瓜录屏了一个非常棒的动画效果解释:

image.png


最后 JS 题解:

var maxSlidingWindow = function (nums, k) {
  // 队列数组(存放的是元素下标,为了取值方便)
  const q = [];
  // 结果数组
  const ans = [];
  for (let i = 0; i < nums.length; i++) {
    // 若队列不为空,且当前元素大于等于队尾所存下标的元素,则弹出队尾
    while (q.length && nums[i] >= nums[q[q.length - 1]]) {
      q.pop();
    }
    // 入队当前元素下标
    q.push(i);
    // 判断当前最大值(即队首元素)是否在窗口中,若不在便将其出队
    while (q[0] <= i - k) {
      q.shift();
    }
    // 当达到窗口大小时便开始向结果中添加数据
    if (i >= k - 1) ans.push(nums[q[0]]);
  }
  return ans;
};

实际上,滑动窗口还是有很多扩展的空间,即使是窗口滑动,怎么滑,滑动后怎么做,里面就存在很大的解题思路的差异!

以上。


相关文章
|
7月前
|
算法
【算法专题突破】滑动窗口 - 长度最小的子数组(9)
【算法专题突破】滑动窗口 - 长度最小的子数组(9)
22 0
|
6天前
|
机器学习/深度学习 算法 测试技术
【单调栈】3113. 边界元素是最大值的子数组数目
【单调栈】3113. 边界元素是最大值的子数组数目
|
6天前
|
弹性计算 运维 算法
证书编号最大值
【4月更文挑战第30天】
12 0
|
6天前
|
算法 测试技术 C#
【map】【滑动窗口】C++算法:最小区间
【map】【滑动窗口】C++算法:最小区间
|
6天前
|
算法 C++
(C++)长度最小的子数组--滑动窗口
(C++)长度最小的子数组--滑动窗口
25 0
|
5月前
不用数组求多个数的最小值
不用数组求多个数的最小值
19 0
交换最小值和最大值
交换最小值和最大值
133 0
|
算法
LeetCode每日1题--滑动窗口最大值
LeetCode每日1题--滑动窗口最大值
69 0
|
存储
239.滑动窗口最大值
239.滑动窗口最大值
56 0
交换最小值和最大值 (15 分)
交换最小值和最大值 (15 分)
215 0