在解决几何问题时,我遇到了一种称为滑动窗口算法的方法。
无法真正找到任何研究材料/细节。
算法是什么?
答案 0 :(得分:97)
一般来说,滑动窗口是在底层集合上运行的子列表。即,如果你有像
这样的数组[a b c d e f g h]
大小为3的滑动窗口会像
一样在它上面运行[a b c]
[b c d]
[c d e]
[d e f]
[e f g]
[f g h]
如果你想要计算一个运行平均值,或者想要创建一组所有相邻对等,这很有用。
答案 1 :(得分:18)
我认为它更多是一种技术而不是算法。这是一种可以在各种算法中使用的技术。
我认为通过以下示例可以最好地理解该技术。假设我们有这个数组:
[ 5, 7, 1, 4, 3, 6, 2, 9, 2 ]
我们如何找到五个连续元素的最大和?好吧,我们首先看一下5, 7, 1, 4, 3
,看得出总和为20
。然后,我们来看下五个连续的元素集,即7, 1, 4, 3, 6
。它们的总和为21
。这比我们以前的总和还多,所以7, 1, 4, 3, 6
是目前为止我们迄今为止最好的。
让我们看看是否可以改善。 1, 4, 3, 6, 2
?不,总计为16
。 4, 3, 6, 2, 9
?总计为24
,所以现在这是我们得到的最佳顺序。现在我们进入下一个序列3, 6, 2, 9, 2
。这等于22
,没有超过我们目前最好的24
。我们已经到了尽头,所以我们完成了。
在代码中实现此功能的蛮力如下:
const getMaxSumOfFiveContiguousElements = (arr) => {
let maxSum = -Infinity;
let currSum;
for (let i = 0; i <= arr.length - 5; i++) {
currSum = 0;
for (let j = i; j <= i + 5; j++) {
currSum += arr[j];
}
maxSum = Math.max(maxSum, currSum);
}
return maxSum;
};
这的时间复杂度是多少?是O(n*k)
。外部循环正在遍历n - k + 1
个项目,但是当n
比k
大得多时,我们可以忘记k + 1
部分,而将其称为n
项目。然后,内部循环将遍历k
个项目,因此我们有了O(n*k)
。尝试像这样可视化它:
我们可以将其简化为O(n)
吗?让我们回到这个数组:
[ 5, 7, 1, 4, 3, 6, 2, 9, 2 ]
首先,我们得到5, 7, 1, 4, 3
的总和。接下来,我们需要7, 1, 4, 3, 6
的总和。像这样可视化它,并在每组五个元素的周围都有一个“窗口”。
第一个窗口和第二个窗口有什么区别?好吧,第二个窗口摆脱了左侧的5
,但在右边添加了6
。因此,由于我们知道第一个窗口的总和为20
,所以要获得第二个窗口的总和,我们取那个20
,减去5
,然后加上{{1 }}获得6
。实际上,我们不必遍历第二个窗口中的每个元素并将它们加起来(21
)。那将涉及重复和不必要的工作。
由于7 + 1 + 4 + 3 + 6
是k
,因此滑动窗口方法最终将是两个操作而不是五个操作。这不是一个很大的改进,但是您可以想象,对于更大的5
(和更大的k
),它确实有帮助。
以下是使用滑动窗口技术的代码工作方式:
n
这就是滑动窗口技术的要点。在其他问题中,您可能要做的事情比获取窗口内元素的总和还要复杂。否则,窗口本身的大小可能会有所变化,而不是我们在此处看到的固定大小(五个)。但是,滑动窗口技术的这种基本应用应该为您提供一个基础,您可以以此为基础。
答案 2 :(得分:6)
要添加到以前的答案,这里有更多资源可以很好地说明这一概念。
https://www.youtube.com/watch?v=pBK-lb-k-rs&list=PLEETnX-uPtBXP_B2yupUKlflXBznWIlL5&index=4是我在该主题上发现的最好的东西。
This youtube video是有关leetcode的问题列表,可以使用此技术解决
滑动窗口是顶级公司在编码回合中要求最频繁的主题之一,因此绝对值得花一些时间来掌握这一点
答案 3 :(得分:1)
滑动窗口是一种解决问题的技术,涉及数组/列表。这些问题在O(n ^ 2)或O(n ^ 3)中的蛮力方法中很容易解决,但要使其在O(n)中可解决,则需要更复杂的方法。
关于此的出色文章在这里:https://medium.com/outco/how-to-solve-sliding-window-problems-28d67601a66
答案 4 :(得分:0)
这是大小为n的数组的滑动窗口协议的代码,其中k个数字的总和存储在另一个数组和中。以下代码用Java表示。
import java.io.*;
class deva
{
public static void main(String args[])throws IOException
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(in.readLine());
int[] a = new int[n];
for(int i=0; i<n; i++)
a[i] = Integer.parseInt(in.readLine());
int k = Integer.parseInt(in.readLine());
int[] sum = new int[n-k+1];
for(int i=0; i<k; i++)
sum[0] += a[i];
System.out.println(sum[0]);
for(int i=1; i<n-k+1; i++)
{
sum[i] = sum[i-1] + a[i+k-1] - a[i-1];
System.out.println(sum[i]);
}
}
}