【アルゴリズム】スライディングウィンドウのコードテンプレート、LeetCodeの80問を簡単に解く

序文:

スライディング ウィンドウは、ダブル ポインターの特殊なケースで、左ポインターと右ポインターと呼ぶことができます。スライディング ウィンドウ法は、一般に、特定のシーケンス内の限定された連続部分シーケンスの問題を解決するために使用されます。

スライディング ウィンドウの時間計算量は線形であり、通常は O(n) です. スライディング ウィンドウの左右の境界は左にスライドしません. 左にスライドすることは戻ることと同じです. これはバックトラッキング アルゴリズムであり, 落ちるかもしれません.無限ループに。スライディング ウィンドウは一種のフル トラバーサル問題であり、最後までトラバースする必要があります。

その本質的なアイデアは次のとおりです

  1. スライディング ウィンドウを埋めるために初期化し、最初のスライディング ウィンドウのターゲット値を取得します。
  2. ウィンドウをスライドし続け、前にスライドするたびに要素を削除および追加して、最適なターゲット値を見つける必要があります

1. アルゴリズムの適用シナリオ

キーワード:

  1. XXX条件を満たす(計算結果、出現回数、同時包含)
  2. 最長/最短
  3. 部分文字列/部分配列/部分列

例: 最小の長さの部分配列

2.スライドウィンドウのアイデアテンプレート

2.1. スライディング ウィンドウを使用するためのアイデア (最も長いものを見つける)

————コア: 左右のダブルポインター (L、R) が開始点にあり、R が少しずつ右にスライドして循環します

———— 各スライドプロセス中

If: ウィンドウ内の要素が条件を満たしている場合、R はウィンドウを右に拡張し、最適な結果を更新します。

If: ウィンドウ内の要素が条件を満たさない場合、L はウィンドウを右に縮小します

———Rは終わりを迎える

2.2. スライディングウィンドウを使用するアイデア (最短を見つける)

————コア: 左右のダブルポインター (L、R) が開始点にあり、R が少しずつ右にスライドして循環します

———— 各スライドプロセス中

If: ウィンドウ内の要素が条件を満たしている場合、L はウィンドウを右に縮小し、最適な結果を更新します

If: ウィンドウ内の要素が条件を満たさない場合、R はウィンドウを右に拡張します。

———Rは終わりを迎える

3. スライディング ウィンドウ コード テンプレート

3.1、最長のテンプレート

初始化 left,right,result,bestResult
while("右指针没有到结尾"){
    窗口扩大,加入right对应元素,更新当前result
    while("result不满足要求"){
        窗口缩小,移除left对应元素,left右移
    }
    更新最优结果bestResult
    right++;
}
返回bestResult

3.2、最短のテンプレート

初始化 left,right,result,bestResult
while("右指针没有到结尾"){
    窗口扩大,加入right对应元素,更新当前result
    while("result满足要求"){
        更新最优结果bestResult
        窗口缩小,移除left对应元素,left右移
    }
    right++;
}
返回bestResult

4. 小テスト(アルゴリズム練習)

タイトル: [209. 最小長部分配列]

n 個の正の整数の配列と正の整数のターゲットが与えられます。

この配列内で合計がターゲットとなる最小の連続部分配列 [numsl, numsl+1, ..., numsr-1, numsr] を見つけ、その長さを返します。一致する部分配列が存在しない場合は 0 を返します。

例 1:

输入: target = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的子数组。

例 2:

输入: target = 4, nums = [1,4,4]
输出: 1

ヒント:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

アルゴリズムの実装:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        // 初始化 left,right,result,bestResult
        // result是当前的currSum、bestResult为mixLength
        int left = 0, right = 0,currSum = 0, mixLength = 0;
        // 右指针没有到结尾
        while(right < nums.length){
            // 窗口扩大,加入right对应元素,更新当前
            currSum += nums[right];
            // result满足要求
            while(currSum >= target){
                // 更新最优结果mixLength
                if(right - left + 1 < mixLength || mixLength == 0){
                    mixLength = right - left + 1;
                }
                // 窗口缩小,移除left对应元素,left右移
                currSum = currSum - nums[left];
                left++;
            }
            // right++
            right++;
        }
        // 返回mixLength
        return mixLength;
    }
}

5: まとめ:

5.1: LeetCodeオリジナル問題209練習チャンネル

より多くのアルゴリズムの演習とアルゴリズムのテンプレートについては、私のGitHubをクリックしてください. 作成するのは簡単ではありません. 便利だと思う場合は、GitHubでスター付きの注文を手伝うことができます. ありがとうございます! また、私の github で LeetCode 学習プロジェクトの貢献に参加することも大歓迎です (個人的に私とチャットしてください)。一緒にアルゴリズムに取り組み、学習の道を進むことができます。

おすすめ

転載: blog.csdn.net/gongzi_9/article/details/126033595