什么是滑动窗口算法?例子?

时间:2011-11-25 13:35:04

标签: algorithm sliding-window

在解决几何问题时,我遇到了一种称为滑动窗口算法的方法。

无法真正找到任何研究材料/细节。

算法是什么?

5 个答案:

答案 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?不,总计为164, 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个项目,但是当nk大得多时,我们可以忘记k + 1部分,而将其称为n项目。然后,内部循环将遍历k个项目,因此我们有了O(n*k)。尝试像这样可视化它:

enter image description here

我们可以将其简化为O(n)吗?让我们回到这个数组:

[ 5, 7, 1, 4, 3, 6, 2, 9, 2 ]

首先,我们得到5, 7, 1, 4, 3的总和。接下来,我们需要7, 1, 4, 3, 6的总和。像这样可视化它,并在每组五个元素的周围都有一个“窗口”。

enter image description here

第一个窗口和第二个窗口有什么区别?好吧,第二个窗口摆脱了左侧的5,但在右边添加了6。因此,由于我们知道第一个窗口的总和为20,所以要获得第二个窗口的总和,我们取那个20,减去5,然后加上{{1 }}获得6。实际上,我们不必遍历第二个窗口中的每个元素并将它们加起来(21)。那将涉及重复和不必要的工作。

由于7 + 1 + 4 + 3 + 6k,因此滑动窗口方法最终将是两个操作而不是五个操作。这不是一个很大的改进,但是您可以想象,对于更大的5(和更大的k),它确实有帮助。

enter image description here

以下是使用滑动窗口技术的代码工作方式:

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]);
        }
    }
}