科学をはじめ:スライディングウィンドウアルゴリズムとは何ですか
スライド操作の大きいアレイ上のサブリストであるスライディング・ウィンドウの問題を含む、アレイは、基礎となる要素の集合です。
アレイ[ABCDEFGH]、3のサイズと仮定スライディングウィンドウその上をスライドするが、存在します。
[a b c]
[b c d]
[c d e]
[d e f]
[e f g]
[f g h]
それは配列で、このウィンドウを使用することで、通常の状況下で法的セクションが、内側スライドするように動的にいくつかの有用なデータを記録し、多くの場合、大幅アルゴリズムの効率を向上させることができます。
スライディングウィンドウ最大1
スライディングウィンドウの最大値:タイトルは、最初LeetCode番号239の問題から来ています。対象の難易度は、40.5%の現在のレートで、ハードです。
タイトル説明
アレイ所与NUMSは、サイズ持っkは右端アレイに左端のアレイからウィンドウ移動するスライディング。あなただけのスライディングウィンドウで見ることができるk個の中の数字。時間スライディングウィンドウは、右のいずれかに移動します。
最大スライディングウィンドウを返します。
例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
分析タイトル
使用ダブルエンドキュー、キュー内の記憶素子の位置の配列で、および保守は、厳密にキューを下げる,,それがチームの最初の要素である維持すると言うことです最大の現在のキューよりも多く存在する場合には、新しい要素を横断するとき、小さな要素は、減少したキューを確保するためにキューを削除されます。差は、キュー要素の位置Kよりも大きい場合、チームの最初の要素は削除されます。
追加:両端キュー(Dqueue)は何ですか
両端キューキュースタックのデータ構造と性質を持っている「両端キュー」、つまり両端キューの意味。名前が示すように、それはフロントエンドと後端サポートインサートであると操作キューを削除します。
両端キューがキュー(待ち行列)から継承され、その直接の実装がそうでArrayDeque、LinkedListはとがあります。
アニメーションの説明
コードの実装
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//有点坑,题目里都说了数组不为空,且 k > 0。但是看了一下,测试用例里面还是有nums = [], k = 0,所以只好加上这个判断
if (nums == null || nums.length < k || k == 0) return new int[0];
int[] res = new int[nums.length - k + 1];
//双端队列
Deque<Integer> deque = new LinkedList<>();
for (int i = 0; i < nums.length; i++) {
//在尾部添加元素,并保证左边元素都比尾部大
while (!deque.isEmpty() && nums[deque.getLast()] < nums[i]) {
deque.removeLast();
}
deque.addLast(i);
//在头部移除元素
if (deque.getFirst() == i - k) {
deque.removeFirst();
}
//输出结果
if (i >= k - 1) {
res[i - k + 1] = nums[deque.getFirst()];
}
}
return res;
}
}
2.いいえ繰り返し文字は、最長のサブストリングません
タイトルはLeetCode最初の3つの質問から来ていません:最長の文字列のない繰り返しを。29.0パーセントの現在のレートによって難易度ミディアムのタイトル、。
タイトル説明
文字列を考えると、あなたは繰り返された文字が含まれていないかを調べる最長のサブストリングの長さを。
例1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
分析タイトル
文字と、その場所の外観との間のマッピングを確立するために、256ビット整数配列FREGサイズを確立します。
スライディングウィンドウは、ウィンドウのサイズを拡大するために可能な限り、ウィンドウには、繰り返し文字ではない維持し、ウィンドウを右にスライドまま。
- 文字に現在のトラバースが登場したことがない場合は(1)、右ボーダーの拡大を指示。
- (2)文字に現在のトラバースは、狭いウィンドウは(右にインデックス移動を左)、その後、トラバース現在の文字を観察し続けるように思われた場合は、
- (3)リピート(1)(2)、インデックスが左まで再び移動することができません。
- (4)ウィンドウサイズを持つそれぞれが結果RESを更新するために登場し、結果の解像度を維持し、最終的にRESが結果を得る返します。
アニメーションの説明
コードの実装
// 滑动窗口
// 时间复杂度: O(len(s))
// 空间复杂度: O(len(charset))
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int freq[256] = {0};
int l = 0, r = -1; //滑动窗口为s[l...r]
int res = 0;
// 整个循环从 l == 0; r == -1 这个空窗口开始
// 到l == s.size(); r == s.size()-1 这个空窗口截止
// 在每次循环里逐渐改变窗口, 维护freq, 并记录当前窗口中是否找到了一个新的最优值
while(l < s.size()){
if(r + 1 < s.size() && freq[s[r+1]] == 0){
r++;
freq[s[r]]++;
}else { //r已经到头 || freq[s[r+1]] == 1
freq[s[l]]--;
l++;
}
res = max(res, r-l+1);
}
return res;
}
};
3.反復エレメントの存在II
IIの反復要素の存在:タイトルはLeetCodeの最初の219面の問題から来ています。アイテムの難易度は簡単、33.9パーセントの現在の合格率です。
タイトル説明
整数配列と整数所与K、二つの異なるインデックスがアレイ内に存在する場合が決定され、I及びJは、このようなことNUMS [i]はNUMS [j]を=、及びI及びJの差の絶対値の最大値K。
例1:
输入: nums = [1,2,3,1], k = 3
输出: true
例2:
输入: nums = [1,0,1,1], k = 1
输出: true
例3:
输入: nums = [1,2,3,1,2,3], k = 2
输出: false
分析タイトル
解決するために、ルックアップテーブルにスライディングウィンドウを使用してください。
- ルックアップテーブルを設け
record
、挿入要素に各パスを保持するため、record
最大長k
- 反復し
nums
、内のすべての時間を繰り返すrecord
ことが返された場合、同じ要素があるかどうかを調べるためにtrue
、終了を横断 - トラバーサルがあれば
record
検出されない場合、要素の中に挿入record
する、次に参照record
長である場合k + 1
- この時点での場合
record
の長さがあればk + 1
の削除、record
要素、要素がありますnums[i - k]
- あなたは完全な配列を横断した場合は
nums
返却されたが見つかりませんfalse
アニメーションの説明
コードの実装
// 时间复杂度: O(n)
// 空间复杂度: O(k)
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k) {
if(nums.size() <= 1) return false;
if(k <= 0) return false;
unordered_set<int> record;
for(int i = 0 ; i < nums.size() ; i ++){
if(record.find(nums[i]) != record.end()){
return true;
}
record.insert(nums[i]);
// 保持record中最多有k个元素
// 因为在下一次循环中会添加一个新元素,使得总共考虑k+1个元素
if(record.size() == k + 1){
record.erase(nums[i - k]);
}
}
return false;
}
};
4.最小のサブ配列の長さ
部分配列の最小の長さ:タイトルは、最初の209のLeetCodeの問題から来ています。難易度ミディアムのタイトル、今37.7パーセントによります。
タイトル説明
含有所与nは正の整数アレイと正の整数S、アレイと出会う識別≥の連続部分配列の最小の長さ。連続サブ配列修飾が存在しない場合は、0が返されます。
例:
输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
分析タイトル
定義する2つのポインタが左と右、それぞれ、境界位置サブアレイを中心に記録されています。
- (1)右に右ように、サブアレイ及びより大きい又は所定の値に等しいが、アレイの右端に達するまで。
- (2)最短距離を更新し、正しいもの、合計マイナス除去値として残します。
- (3)リピート(1)(2)の工程は、右端に到達するまで、左及び臨界位置に到達
アニメーションの説明
スライディングウィンドウの長さは、0に一番左の軸を設定されています。
1. Rは、間隔が所定の条件を満たして右までウィンドウが移動を摺動開始即ち7よりも大きいと、第三の要素2が停止し、この場合、4現在の最適な長さ
2.スライディングウィンドウLの左端には、スライディングウィンドウのサイズ、最初の要素3上のストップを縮小、移動を開始し、セクションと(この時点ではない以上7)所定の条件を満たさないように、この時間間隔は、6であります
スライディングウィンドウR 3右に移動し続け、第4要素4が停止され、このときビット10が、それでも4の最適な長さであります
コードの実装
// 滑动窗口的思路
// 时间复杂度: O(n)
// 空间复杂度: O(1)
class Solution {
public int minSubArrayLen(int s, int[] nums) {
int l= 0,r = -1; // nums[l...r]为我们的滑动窗口
int sum = 0;
int result = nums.length + 1;
while (l < nums.length){ // 窗口的左边界在数组范围内,则循环继续
if( r+1 <nums.length && sum < s){
r++;
sum += nums[r];
}else { // r已经到头 或者 sum >= s
sum -= nums[l];
l++;
}
if(sum >= s){
result = (r-l+1) < result ? (r-l+1) : result ;
}
}
if(result==nums.length+1){
return 0;
}
return result;
}
}
❤️3つのことを読んで:
あなたは非常に感激このコンテンツを見つけた場合、私は3私が忙しい助けるためにあなたを招待したいです:
- 親指、より多くの人々がこのコンテンツを見ることができないように(何も賞賛を収集ポイントを、いじめ-_-)
- 我々は長期的な関係になるように、私と列を見ます
- 国民の関心番号「5分学習アルゴリズム」、最新記事のアルゴリズムを読むために初めて、公衆番号1024返信の背景があなたの50冊のアルゴリズムのプログラミングの本を与えます。