滑動窗口算法(思想)


題目:

給定一個字符串,請你找出其中不含有重復字符的 最長子串 的長度。

示例 1:

輸入: "abcabcbb"
輸出: 3
解釋: 因為無重復字符的最長子串是 "abc",所以其長度為 3。

 

子串和串中字符的對比,只要出現相同字符都算重復,肯定要用到嵌套循環。

如果暴力枚舉,每個長度的子串都拿出來做自檢,時間復雜度會比較高。

使用滑動窗口的思想,對錯誤信息進行合理利用,可以有效減少執行次數。

 

C語言解法:

int lengthOfLongestSubstring(char * s){
    int i = 0, j = 0;
    int maxlen = 0;
    int curlen = 0;
    int len = strlen(s);
    if (len == 0)
        return 0;
    for (; j < len && len - i > maxlen; j++) {
        curlen++;
        for (int k = i; k <= j; k++) {
            if (s[k] == s[j + 1]) {
                if (curlen > maxlen)
                    maxlen = curlen;
                i = k + 1;
                curlen = j - i + 1;
                break;
            }
        }
    }
    if (curlen > maxlen)
        return curlen;
    else
        return maxlen;
}

 

滑動窗口初聽覺得抽象模糊,其實拿卷尺一對比很好理解

一個字符串,要在里面找出最長且沒有重復字符的子串,就像拿着卷尺在上面不停地縮拉測量

子串就是這個卷尺的伸出部分,即一個窗口,左邊縮進,右邊拉出

因為不能有重復的字符,在右端逐漸拉長的過程中,每新增加的一個新字符都要拿來和左側子串中的字符做對比

在上面的程序里,用 i 指向卷尺頭部,用 j 指向卷尺尾部,k 則作為子串中字符的索引

每次對比開始時,用 i 的值初始化 k,當找到重復字符時,又將 k + 1的值賦給 i,即直接將窗口的左側移動到重復字符的下一個字符位置

窗口右側每次向右滑動一格,如果窗口中子串包含窗口右側下一個字符,左側滑動一格或多格 

與枚舉法相比,由於利用了子串中重復字符的位置,直接將窗口左側跳到該字符的下一個位置,每次檢查出重復減少了 k - i 個子串的自檢

 

題目

給定數組,獲取數組中n個連續元素最大的和

 

C語言解法:

 1 int maxSumSub(nums, n) {
 2     int len = (int) sizeof(nums) / sizeof(int);
 3     int maxsum = 0;
 4     if (n > len) {
 5         return 0;
 6     }
 7     for (int i = 0; i < n; i++) {
 8         maxsum += nums[i];
 9     }
10 
11     int windowsum = maxsum;
12 
13     for (int i = n; i < len; i++) {
14         windowsum += nums[i] - nums[i - n];
15         if (windowsum > maxsum)
16               maxsum = windowsum;
17     }
18     return maxsum;
19 }

 

 

和上面的求最長無重復子串類似,如果使用枚舉法,假設數組長度為 len,則要求出 len - n  + 1 個和,進行 len - n 次對比 

如果用滑動窗口法,基本思想是,每次向右滑動時,窗口右側進入的新元素減去左側退出的舊元素,得到的結果與上次的和相加得到新的和

這樣做的巧妙之處在於,無論題設n有多大,每次窗口移動后,計算新和,只需將窗口兩端進出的新舊元素相減,得到的結果與舊和相加就可以得到新和

 

總結

上述兩個題目,分別用到了動態滑動窗口和固定滑動窗口,即在滑動時長度變化和不變的兩種窗口

可以看到,滑動窗口的應用場景有幾個特點:

1. 需要輸出或比較的結果在原數據結構中是連續排列的(字符串中的連續不重復子串,數組中的連續元素最大和)

2. 每次窗口滑動時,只需觀察窗口兩端元素的變化,無論窗口多長,每次只操作兩個頭尾元素,當用到的窗口比較長時,可以顯著減少操作次數

3. 窗口內元素的整體性比較強,窗口滑動可以只通過操作頭尾兩個位置的變化實現,但對比結果時往往要用到窗口中所有元素(檢查窗口中是否含有重復字符,對比窗口中元素的和)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM