滑動視窗問題總結

wochh發表於2024-09-23

適用範圍

1、一般是字串或者列表
2、一般是要求最值(最大長度,最短長度等等)或者子序列

演算法思想

1、在序列中使用雙指標中的左右指標技巧,初始化 left = right = 0,把索引閉區間 [left, right] 稱為一個視窗。
2、先不斷地增加 right 指標擴大視窗 [left, right],直到視窗中的序列符合要求。
3、此時,停止增加 right,轉而不斷增加 left 指標縮小視窗 [left, right],直到視窗中的序列不再符合要求。同時,每次增加 left前,都要更新一輪結果。
4、重複第 2 和第 3 步,直到 right 到達序列的盡頭。
思路其實很簡單:第 2 步相當於在尋找一個可行解,然後第 3 步在最佳化這個可行解,最終找到最優解。左右指標輪流前進,視窗大小增增減減,視窗不斷向右滑動。

Note: 因為每次right找到新的字串後會向後移動,指向的是下一個待判斷的字元,所以,如果是判斷字串的長度應該是用right-left,而不是right-left+1

程式碼模板

func slidingWindowTemplate(s string) int {
    left, right := 0, 0 // 初始化視窗的左右邊界
    result := 0 // 用於儲存結果
    window := make(map[byte]int) // 記錄視窗中元素的頻率,或其他視窗狀態

    // 遍歷陣列或字串
    for right < len(s) {
        // 1. 擴充套件視窗,更新視窗狀態
        charRight := s[right]
        window[charRight]++ // 將字元加入視窗
        right++

        // 2. 如果視窗不滿足條件,收縮視窗
        for /* 條件: 視窗不滿足要求 */ {
            charLeft := s[left]
            window[charLeft]-- // 將左邊的字元移出視窗
            left++
        }

        // 3. 更新結果
        result = max(result, right - left) // 例如,記錄視窗的最大長度
    }

    // 4. 返回最終結果
    return result
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}



相關文章