在解决几何问题时,我遇到了一种称为“滑动窗口算法”的方法。
真的找不到任何学习资料/细节。
算法是关于什么的?
在解决几何问题时,我遇到了一种称为“滑动窗口算法”的方法。
真的找不到任何学习资料/细节。
算法是关于什么的?
Answers:
滑动窗口是解决涉及阵列/列表的问题的技术。使用O(n ^ 2)或O(n ^ 3)中的蛮力方法可以轻松解决这些问题。 使用“滑动窗口”技术,我们可以将时间复杂度降低为O(n)。
伟大的文章在这里:https://medium.com/outco/how-to-solve-sliding-window-problems-28d67601a66
因此,您要做的第一件事就是识别使用滑动窗口范式的问题。幸运的是,有一些常见的赠品:
问题将涉及一个有序且可迭代的数据结构,如数组或字符串
您正在该数组/字符串中寻找某个子范围,例如最长,最短或目标值。
在O(N²),O(2 ^ N)或其他较大的时间复杂度下,有一个简单的幼稚或蛮力解决方案。
但是最大的礼物是,您正在寻找的东西通常是某种最优的,例如恰好满足给定条件的事物的最长序列或最短序列。
我认为它更多的是技术而不是算法。这是一种可以在各种算法中使用的技术。
我认为通过以下示例可以最好地理解该技术。假设我们有这个数组:
[ 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,然后加上6得到21。实际上,我们不必遍历第二个窗口中的每个元素并将它们加起来(7 + 1 + 4 + 3 + 6)。那将涉及重复和不必要的工作。
此处的滑动窗口方法最终是两个操作,而不是五个操作,因为k是5。这并不是一个很大的改进,但是您可以想象,对于更大k(或更大n)的系统确实有帮助。
以下是使用滑动窗口技术的代码工作方式:
const getLargestSumOfFiveConsecutiveElements = (arr) => {
let currSum = getSum(arr, 0, 4);
let largestSum = currSum;
for (let i = 1; i <= arr.length - 5; i++) {
currSum -= arr[i - 1]; // subtract element to the left of curr window
currSum += arr[i + 4]; // add last element in curr window
largestSum = Math.max(largestSum, currSum);
}
return largestSum;
};
const getSum = (arr, start, end) => {
let sum = 0;
for (let i = start; i <= end; i++) {
sum += arr[i];
}
return sum;
};
这就是滑动窗口技术的要点。在其他问题中,您可能要做的事情比获取窗口内元素的总和还要复杂。否则,窗口本身的大小可能会有所变化,而不是我们在此处看到的固定大小(五个)。但是,滑动窗口技术的这一基本应用应该为您提供一个基础,您可以以此为基础。