滑动窗口法_滑动窗法

滑动窗口法

The sliding window method is a common strategy for optimizing an algorithm. This article will use code examples in JavaScript, but the technique is applicable to most languages.

滑动窗口方法是优化算法的常用策略。 本文将使用JavaScript中的代码示例,但是该技术适用于大多数语言。

There are several clues that this is the technique you’ll want to use for a problem. They typically involve unsorted arrays. If you are looking for a contiguous subarray that adheres to certain guidelines, you’ll probably want to use a sliding window. Contiguous means all numbers in the subarray are touching, as in you are not skipping any numbers within the subarray to come up with the answer. For example:

有很多线索表明这是您要用于解决问题的技术。 它们通常涉及未排序的数组。 如果您正在寻找符合某些准则的连续子数组,则可能需要使用滑动窗口。 连续意味着子数组中的所有数字都在接触,因为您不会跳过子数组中的任何数字以得出答案。 例如:

const array = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

In this array, [‘a’, ‘b’, ‘c’] is a contiguous subarray, but [‘b’, ‘d’, ‘e’] is not, because ‘b’ does not touch ‘d’ in the original array.

在此数组中,['a','b','c']是连续的子数组,但是['b','d','e']不是,因为“ b”不会触及原始数组。

We can further classify sliding windows as static window problems or dynamic window problems. In static window problems, you will always be looking at a subarray/substring of a specific length, ex: ‘Find the maximum sum of ‘k’ contiguous integers in an integer array.” Here, you will have a k-sized window that will stay k-sized throughout the problem. Let’s do this one together.

我们可以进一步将滑动窗口分为静态窗口问题动态窗口问题。 在静态窗口问题中,您将始终查看特定长度的子数组/子字符串,例如:“在整数数组中查找'k'个连续整数的最大和。” 在这里,您将拥有一个k大小的窗口,它将在整个问题中保持k大小。 让我们一起做这个。

The brute force solution to the problem would be to add up k integers starting with the first element. Then, add up k integers starting with the second element. Then, add up k integers starting with the third element…until you reach the end of the array. Let’s see some pseudocode for what this involves:

解决该问题的蛮力方法是将第一个元素开始的k个整数相加。 然后,从第二个元素开始累加k个整数。 然后,从第三个元素开始添加k个整数,直到到达数组的末尾。 我们来看一下其中涉及的一些伪代码:

let k = 5;
let array = [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6];//iterate from the first element, and on each iteration add the bold numbers together://first iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//second iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//third iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//fourth iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//fifth iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//sixth iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//seventh iteration:[1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]//return the maximum sum found

Can you see all of the overlap? This is what we will get rid of using the sliding window method.

您能看到所有重叠吗? 这就是我们将使用滑动窗口方法摆脱的东西。

In the sliding window method, instead of adding up k elements each time, we will keep track of the previous sum, slide the window over, and readjust the sum.

在滑动窗口方法中,我们将跟踪先前的总和,将窗口滑过并重新调整总和,而不是每次都添加k个元素。

let k = 5;
let array = [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6];//iterate from the first element, and on each iteration add the bold numbers together://first iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//sum = 1 + 5 + 3 + 6 + 8 = 23//second iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//sum = sum - 1 + 3 = 25 => here we have slid the window, so 1 is no longer a part, and 3 has been added. We subtract and add to reflect this.
//third iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//sum = sum - 5 + 6 = 26
//fourth iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//sum = sum - 3 + 8 = 31
//fifth iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//sum = sum - 6 + 0 = 25
//sixth iteration: [1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//sum = sum - 8 + 3 = 20
//seventh iteration:[1, 5, 3, 6, 8, 3, 6, 8, 0, 3, 6]
//sum = sum - 3 + 6 = 23//return the maximum sum found => 31

This solution gets rid of the overlap and gives us a linear solution with respect to the size of the input array! It may not seem that useful for problems where k is small, but imagine a scenario with an array of size 100 and a k of size 50. You are getting rid of so much overlap in that case!

该解决方案消除了重叠,并为我们提供了有关输入数组大小的线性解决方案! 对于k较小的问题,它似乎没有什么用处,但可以想象一下一个数组,数组大小为100,而ak的大小为50。在这种情况下,您将避免太多重叠!

Here is solution code for this in JavaScript:

这是JavaScript中解决方案的代码:

function max_sub_array_of_size_k(k, arr) {
let maxSum = 0,
let windowSum = 0,
let start = 0;
for (let end = 0; end < arr.length; end++) {
windowSum += arr[end];
if (end >= k - 1) {
maxSum = Math.max(maxSum, windowSum);
windowSum -= arr[start];
start--;
}
}
return maxSum;
}

Next, lets talk about what I have been calling dynamic window problems. This method feels similar to two pointer methods, but instead of just caring about each pointer, you care about everything between the pointers! An example of this would be: “Find the length of the smallest contiguous subarray with a sum greater than or equal to a given value”,

接下来,让我们谈谈我所说的动态窗口问题。 此方法感觉类似于两个指针方法,但是您不仅关心每个指针,还关心指针之间的所有内容! 这样的一个例子是:“找到最小连续子数组的长度,其总和大于或等于给定值”,

In this case, we are checking different window lengths. For the brute force solution, we would start with index 0 and add subsequent indexes until we have reached the sum. Then we would start at index 1 and do the same thing, until we reach the end of the array. This is inefficient for the same overlapping reason we had before!

在这种情况下,我们要检查不同的窗口长度。 对于强力解决方案,我们将从索引0开始并添加后续索引,直到达到总和。 然后,我们将从索引1开始并执行相同的操作,直到到达数组的末尾。 由于之前的重叠原因,这效率很低!

Instead, we want to start the window on the first element, and expand the window until we reach the sum. Then, we shrink the window by moving the start of the window ahead. Once we are lower than the sum, we have to expand the window again by moving the end of the window ahead! Let’s look at some pseudocode for this:

取而代之的是,我们要在第一个元素上启动窗口,并扩大窗口直到达到总和。 然后,我们通过向前移动窗口的起点来缩小窗口。 一旦低于总和,就必须通过向前移动窗口的末端来再次扩展窗口! 让我们来看一些伪代码:

array: [1, 5, 3, 6, 8, 3]
sum: 10We start by setting the window to be length 1, looking only at the first element.
[1, 5, 3, 6, 8, 3]
1 is less than the sum, so we expand the window until we are greater than or equal to the sum:
[1, 5, 3, 6, 8, 3] => length = 4, windowSum = 15
Now we shrink the window by moving the start and check if it's still greater than the sum
[1, 5, 3, 6, 8, 3] => length = 3, windowSum = 14
We update our min length to be 3!
[1, 5, 3, 6, 8, 3] => windowSum = 9
Now the sum is too small, so we expand our window again
[1, 5, 3, 6, 8, 3] => length = 3, windowSum = 17
We are big enough to shrink the window
[1, 5, 3, 6, 8, 3] => length = 2, windowSum = 14
Update our min length to be 2! Shrink the window.
[1, 5, 3, 6, 8, 3] => windowSum = 8
Too small, expand the window!
[1, 5, 3, 6, 8, 3] => length = 2, windowSum = 11
We have reached the end of the array, and the smallest window we saw that was greater than the test sum was 2 elements in length.

Go ahead and try to code this one out on your own! Good luck!

继续尝试自己编写代码! 祝好运!

翻译自: https://medium.com/@sarah.larkworthy/the-sliding-window-method-90e36c886650

滑动窗口法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值