滑动窗口算法

给定一个整型数组和一个数字s,找到数组中的最短连续子数组,使得连续子数组的和sum>=s,返回这个最短连续子数组的长度值

如给定[2,3,1,2,4,3],s=7

答案为[4,3],返回2

第一种解法就是暴力解法,采用双循环来遍历所有的子数组,代码如下

#include<iostream>

using namespace std;

int GetSubArrayLen(int* Arr,int ArrLen,int Val);

int main(void)
{
    int* Array;
    int ArrLen;

    cin >> ArrLen;
    Array = new int[ArrLen];
    for (int i = 0; i < ArrLen; ++i)
        cin >> Array[i];
    int Val;
    cin >> Val;

    cout << GetSubArrayLen(Array, ArrLen, Val)<<endl;
    system("pause");
    return 0;
}

int GetSubArrayLen(int* Arr,int ArrLen,int Val)
{
    int Len = 0;
    int sum = 0;
    for (int t = 0; t < ArrLen; ++t)
        sum += Arr[t];
    if (sum > Val)
        Len = ArrLen;
    else
        return 0;

    for(int i=0;i<ArrLen;++i)
        for (int j = ArrLen - 1; j > i; --j)
        {
            sum = 0;
            for (int t = i; t <= j; ++t)
                sum += Arr[t];
            if(sum>=Val&&((j-i+1)<=ArrLen))
                Len=j-i+1;
        }
    return Len;
}

这种方法的时间复杂度为O(n^3),可以将数组中每个元素的值替换为前面所有数组的和,比如将arr[3]的值变为arr[0]+arr[1]+arr[2]+arr[3],这样求解一段子数组的和时,比如求2~4的子数组之和,就用修改后的arr[4]-arr[2]就可以了,这样可以省去双循环中循环求和步骤门将时间复杂度降到O(n^2)

还有一种滑动窗口方法

连个指针L和R,L表示滑窗的左边框,R表示滑窗的右边框

左边框向右滑动使窗口变小,右边框向右滑动使窗口变大,开始左右边框是重合在一起的,窗口的和就是重合点所在的数

1,先将R向右滑动,当和恰好>=s时,记录下滑窗的子数组长度,如果这个长度小于原来的长度,就更新子数组长度

2,L向右滑动,判断是否仍然>=s,如果满足条件就继续向右滑动

3,如果<s则将R向右滑动,重复1

代码如下

#include<iostream>

using namespace std;

int GetSubArrayLen(int* Arr,int ArrLen,int Val);
int WindowValue(int* Arr, int L, int R);

int main(void)
{
    int* Array;
    int ArrLen;

    cin >> ArrLen;
    Array = new int[ArrLen];
    for (int i = 0; i < ArrLen; ++i)
        cin >> Array[i];
    int Val;
    cin >> Val;

    cout << GetSubArrayLen(Array, ArrLen, Val)<<endl;
    system("pause");
    return 0;
}

int GetSubArrayLen(int* Arr,int ArrLen,int Val)
{
    int Len = 0;
    int sum = 0;
    for (int t = 0; t < ArrLen; ++t)
        sum += Arr[t];
    if (sum > Val)
        Len = ArrLen;
    else
        return 0;

    int TempLen = 0;
    int L = 0, R = 0;
    while (R < ArrLen)
    {
        while ((WindowValue(Arr, L, R) < Val)&&(R<ArrLen))
            R++;
        while ((WindowValue(Arr, L, R) >= Val)&&(L<=R))
        {
            TempLen = R - L + 1;
            if (TempLen <= Len)
                Len = TempLen;
            L++;
        }
    }
    return Len;
}

int WindowValue(int* Arr, int L, int R)
{
    int Sum = 0;
    for (int i = L; i < R + 1; ++i)
        Sum += Arr[i];
    return Sum;
}
原文地址:https://www.cnblogs.com/wangtianning1223/p/13812240.html