序文:
スライディング ウィンドウは、ダブル ポインターの特殊なケースで、左ポインターと右ポインターと呼ぶことができます。スライディング ウィンドウ法は、一般に、特定のシーケンス内の限定された連続部分シーケンスの問題を解決するために使用されます。
スライディング ウィンドウの時間計算量は線形であり、通常は O(n) です. スライディング ウィンドウの左右の境界は左にスライドしません. 左にスライドすることは戻ることと同じです. これはバックトラッキング アルゴリズムであり, 落ちるかもしれません.無限ループに。スライディング ウィンドウは一種のフル トラバーサル問題であり、最後までトラバースする必要があります。
その本質的なアイデアは次のとおりです。
- スライディング ウィンドウを埋めるために初期化し、最初のスライディング ウィンドウのターゲット値を取得します。
- ウィンドウをスライドし続け、前にスライドするたびに要素を削除および追加して、最適なターゲット値を見つける必要があります
1. アルゴリズムの適用シナリオ
キーワード:
- XXX条件を満たす(計算結果、出現回数、同時包含)
- 最長/最短
- 部分文字列/部分配列/部分列
例: 最小の長さの部分配列
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 学習プロジェクトの貢献に参加することも大歓迎です (個人的に私とチャットしてください)。一緒にアルゴリズムに取り組み、学習の道を進むことができます。