Bootstrap

算法总结-滑窗算法(一)

今有问题如下,给定一个整数数组,计算长度为‘k’的连续子数组的最大总和。

输入:arr[] = {100, 200, 300, 400};

           k = 2;

输出:700

解释:300 + 400 = 700

这是一道简单的题目,用暴力法也可以直接解答出来,但今天我们要讨论的是滑窗算法,所以不对暴力解法作太多解答。但为了方便对比,仍然给出暴力解法的答案。


暴力法

unsigned int len = 4;
unsigned int sum = 0;
for (int i = 0; i < len - 1; i++) {
    for (int j = i+1; j < i+k; j++) {
        sum = sum > (arr[i] + arr[j]) ? sum : (arr[i] + arr[j]);
    }
}

暴力解法包含两个for循环,时间复杂度为O(k*n)。

滑动窗口法

滑动窗口算法可以将嵌套的循环问题,转换为单循环问题,降低时间复杂度。

根据示例,当 k 等于 2 时,我们维护一个长度为 2 的窗口。

a、窗口内的值的和保存在一个变量中;

b、通过不断的往右滑动来算出当前窗口的值,并与保存的最大值作比较;

c、当窗口滑动到最右边时终止滑动;

    unsigned int len = 4; 
    for (int i = 0; i < k; i++) {  //首先计算出第一个窗口的值. //窗口大小为2
        sum += arr[i];
    }
    unsigned int max = sum;
    for (int i = k; i < len; i++) {
        sum += arr[i] - arr[i-k];  //新窗口的值= 前一个窗口的值 + 新进入窗口的值 - 移出窗口的值
        max = sum > max ? sum:max;
    }
    return max;

我们在一个循环中计算出了长度为 'k' 的子数组的最大总和,它的时间复杂度是 O(n)。我们可以使用滑动窗口算法解决 查找最大/最小k子阵列,XOR,乘积,求和等问题。

;