【leetcode】滑動窗口專題

文章目錄

  • 1.長度最小的子數組
  • 2.無重復字符的最長子串
  • 3.最大連續1的個數III
  • 4.將x減小到0的最小操作數
  • 5.水果成籃
  • 6.找到字符串中所有字母異位詞
  • 7.串聯所有單詞的子串
  • 8.最小覆蓋子串

在這里插入圖片描述

1.長度最小的子數組

在這里插入圖片描述
leetcode 209.長度最小的子數組

看到這個題目,第一眼肯定想到的是暴力枚舉,那我們就來枚舉以下試試:
在這里插入圖片描述

很明顯,暴力枚舉的方式會超時。

在這里插入圖片描述

那有沒有哪里能優化一下,讓它不超時呢?我們來分析一下:

在暴力枚舉中,我們的 right 每次都會回到left位置的下一個,然后和 left 一起重新枚舉。

在這里插入圖片描述
優化枚舉具體步驟如下:

在這里插入圖片描述

在上面的枚舉過程中,我們的藍色框就像是一個滑動的、大小不固定的窗口,我們稱這種方式叫做滑動窗口

對與滑動窗口而言,無非就以下幾個步驟:
在這里插入圖片描述
每個題目窗口的起始、更新結果的位置是不固定的,具體情況具體分析。

按照滑動窗口的方法,我們的代碼就不會超時啦。
在這里插入圖片描述
簡單分析以下時間復雜度:從代碼看好像是O(n2),但是由于我們滑動窗口的思想,兩個指針是同向遍歷,而且不會回退;當right指針結束時,循環結束,所以它的時間復雜度是O(n)。

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int ret = INT_MAX;int n = nums.size();int sum = 0;for(int left = 0, right = 0; right < n; right++)//right后移{//進窗口sum += nums[right];//判斷窗口while(sum >= target){//符合條件,更新結果ret = min(ret,right - left + 1);sum -= nums[left];//出窗口left++;}  }if(ret == INT_MAX)return 0;elsereturn ret;}
};

2.無重復字符的最長子串

在這里插入圖片描述
leetcode 3.無重復字符的最長字串

這一題首先想到的方法無疑就是枚舉,然后統計每個字符出現的次數;如果一個字符出現了兩次,那么當前字符對應的字符串就是最長子串
在這里插入圖片描述
我們發現,暴力枚舉法也可以過
在這里插入圖片描述

那有沒有更優的解法呢?我們來分析一下
在這里插入圖片描述
上述解法不就是滑動窗口嗎?
在這里插入圖片描述

此時的時間復雜度O(n)是不是比暴力枚舉O(n2)更加優秀了

class Solution {
public:int lengthOfLongestSubstring(string s) {int n = s.size();int hash[128] = { 0 };int ret = 0;for(int left = 0, right = 0; right < n; right++){hash[s[right]]++;//入窗口,先記錄當前while(hash[s[right]] > 1)//若s[right]重復{hash[s[left]]--;//出窗口left++;}ret = max(ret,right - left + 1);//更新結果}return ret;}
};

3.最大連續1的個數III

在這里插入圖片描述
leetcode 1004.最大連續1的個數III

分析題目可知,其中0可以翻轉的意思就是:0可以當作1來用。那我們的目標就是找一段包含1的個數最大連續的區間,該區間中0的個數不可以超過k。

這一題的暴力枚舉法就不演示了,我們直接上滑動窗口。
在這里插入圖片描述
在這里插入圖片描述
這樣我們的代碼就過咯
在這里插入圖片描述

class Solution {
public:int longestOnes(vector<int>& nums, int k) {int n = nums.size();int zero = 0;//統計0的個數int ret = 0;for(int left = 0, right = 0; right < n; right++){//進窗口,判斷是否是0if(nums[right] == 0)zero++;//判斷0的個數是否大于kwhile(zero > k){//判斷是否是0出窗口if(nums[left] == 0)zero--;left++;}//更新結果ret = max(ret,right-left+1);}return ret;}
};

4.將x減小到0的最小操作數

在這里插入圖片描述
leetcode 1658.將x減小到0的最小操作數

通過讀題我們可以發現,它一會是左邊,一會是右邊,是不是很難控制;那應該怎么做呢?
正難則反

  • 我們在數組中找一塊連續的區間,數組中去除該連續區間的內容,剩下的內容剛好等于x時,那我們是不是就找到了一種情況
  • 該連續區間就是數組中元素的總和減去x
  • 當在數組中找到的一塊連續區間最長時,我們就找到了最佳的解決方案。

在這里插入圖片描述
還是像前面的題目一樣,使用滑動窗口。

在這里插入圖片描述

class Solution {
public:int minOperations(vector<int>& nums, int x) {int ret = 0;int total = 0;int n = nums.size();for(auto e : nums)total += e; //求數組的和int target = total - x; //target為要找的連續區間的總大小if(target < 0)//細節return -1;if(total == x)return n;int sum = 0;for(int left = 0, right = 0; right < n; right++){sum += nums[right];//進窗口while(sum > target){sum -= nums[left];left++;}if(sum == target)//找到目標區間,取長的一個ret = max(ret,right - left + 1);}if(ret == 0)return -1;elsereturn n - ret;}
};

5.水果成籃

在這里插入圖片描述
leetcode 904.水果成籃

這個題目這么長,它表達的是什么意思呢?

只有兩個籃子,籃子里的水果只能有兩種,并且不能跨越樹木,求你所經過的樹的最多的個數。
那又是求一段連續區間的長度,我們可以使用滑動窗口

在這里插入圖片描述
那我怎么知道當前摘的水果有幾種呢?----使用哈希表統計
在這里插入圖片描述
我們可以發現,使用哈希表的消耗還是挺大的,能不能再優化一下呢?

由題目要求可知,種類是小于105的,所以我們可以直接使用一個數組+一個變量(記錄種類)
在這里插入圖片描述

這樣我們的效率就提升了很多。
在這里插入圖片描述

class Solution {
public:int totalFruit(vector<int>& fruits) {int n = fruits.size();int ret = 0;int hash[100000] = { 0 };int kinds = 0;for(int left = 0, right = 0; right < n; right++){if(hash[fruits[right]] == 0)//判斷是否是新種類水果kinds++;hash[fruits[right]]++;//進窗口while(kinds > 2)//判斷總類是否大于2{hash[fruits[left]]--;//出窗口if(hash[fruits[left]] == 0)kinds--;  //去除該種類left++;}ret = max(ret,right - left + 1);}return ret;}
};

6.找到字符串中所有字母異位詞

在這里插入圖片描述

leetcode 438.找到字符串中所有字母異位詞

分析題目可知,就是在s串中找出p串(p串中的字符順序可打亂)。
那我們就可以找一個長度和p相等,且字符種類、個數和p串相等的子串即可

所以我們可以使用兩個哈希表,分別統計p串和s串中字符的種類和個數。

那我們先使用暴力枚舉的方式試一下:
在這里插入圖片描述
在這里插入圖片描述

那兩個哈希表是如何進行比較的呢?

  1. 首先使用hash1記錄p串中字符的類型個數
  2. 遍歷s,找長度和p相等的子串,同時hash2存放當前字符
    a、若hash2[right] <= hash1[right]時,“有效字符”種類增加
    b、若hash2[right] > hash2[right],“有效字符”種類不變

在這里插入圖片描述
暴力枚舉的方式確實可以過,但效率比較低下。
既然是找一段連續的區間,那能不能使用滑動窗口呢?我們來試一下
在這里插入圖片描述
這樣我們的效率就高很多了
在這里插入圖片描述

class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> ret;int len = p.size();int hash1[128] = { 0 };for(auto e: p)hash1[e]++;//統計p串的種類int n = s.size();int hash2[128] = { 0 };//統計子串種類int kinds = 0;int tmp = 0;for(int left = 0,right = 0; right < n ; right++){hash2[s[right]]++; //進窗口tmp++;//子串長度增加if(hash2[s[right]] <= hash1[s[right]])kinds++;//"有效字符"種類增加if(tmp > len){if(hash2[s[left]] <= hash1[s[left]])kinds--;//left位置為“有效字符”,種類減少hash2[s[left]]--;tmp--;left++;}if(tmp == len)if(kinds == len)ret.push_back(left);}return ret;}
};

7.串聯所有單詞的子串

在這里插入圖片描述

leetcode 30.串聯所有單詞的子串

這一題和前一道題目類似,只不過這里是將字符換成了字符串而已。因此我們還是使用:滑動窗口+哈希表的方式解決。
在這里插入圖片描述

解題步驟:

  1. 先使用hash1統計words中字符串的種類
  2. 使用滑動窗口(由于字符串的長度是固定的,所以可以直接跳躍長度)
    a、定義起始:left、right
    b、字符串進窗口,需要使用字符串的函數substr進行裁剪
    c、判斷字符串的種類
    ? 是否出窗口
    ? 更新結果

在這里插入圖片描述
然而,代碼只過了一部分,分析一下它的測試用例發現,
在這里插入圖片描述
這樣代碼就過啦!

在這里插入圖片描述

class Solution {
public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> ret;unordered_map<string,int> hash1;for(auto& e : words)hash1[e]++;//統計要求的字符串種類int n = s.size();int len = words[0].size();//固定的字符串長度int m = words.size();//數組長度for(int i=0; i < len; i++){unordered_map<string,int> hash2;int count = 0;for(int left = i, right = i; right <= n -len; right+= len){string in = s.substr(right,len);//裁剪字符串hash2[in]++;//進窗口if(hash2[in] <= hash1[in])count++;//統計當前字符串數量if(right - left + 1 > m*len)//判斷字符串數量是否大于字符數組{string out = s.substr(left,len);if(hash2[out] <= hash1[out])count--;hash2[out]--;//出窗口left += len;}if(count == m)ret.push_back(left);}}return ret;}
};

8.最小覆蓋子串

在這里插入圖片描述
leetcode 76.最小覆蓋子串

該題和上一題的解題思路差不多,也是在s串中找t串的全部字符,只不過這里要將找到的字符串的最小的一個返回而已。

我們依舊使用滑動窗口+哈希表的方式解決。

  1. 使用hash1統計t串中字符的種類和數量
  2. 滑動窗口:定義起始位置 left, right
    a、進窗口
    b、判斷是否出窗口
    c、更新結果(僅需記錄串的起始位置和長度,最后在切割子串)

在這里插入圖片描述

在代碼中在記錄字符串的起始位置和長度即可,這樣我們的代碼就過啦。

在這里插入圖片描述

class Solution {
public:string minWindow(string s, string t) {int hash1[128] = { 0 };for(auto e : t)hash1[e]++;//統計t串的字符種類和數量int m = t.size();int n = s.size();int hash2[128] = { 0 };int count = 0;int start = 0;int len = INT_MAX;for(int left = 0, right = 0; right < n; right++){hash2[s[right]]++;//進窗口if(hash2[s[right]] <= hash1[s[right]])//是否更新有效字符count++;while(count >= m)//是否出窗口{if(count == m)//找到符合種類的子串{//取長度小的一個int curlen = right - left + 1;if(curlen < len){start = left;len = curlen;}}//出窗口if(hash2[s[left]] <= hash1[s[left]])count--;hash2[s[left]]--;left++;}}if(len == INT_MAX)return "";elsereturn s.substr(start,len);}
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/44969.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/44969.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/44969.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

正則表達式控制everything等搜索工具更快速的對需要的內容進行檢索

正則表達式對文件搜索工具規則 表格模式 匹配模式描述abgr(ale)y匹配 “gray” 或 “grey”.匹配除換行符之外的任意單個字符[abc]匹配字符 “a”、“b” 或 “c” 中的任意一個[^abc]匹配除了 “a”、“b”、“c” 之外的任意單個字符[a-z]匹配小寫字母 a 到 z 之間的任意一…

科普文:深入理解Mybatis

概敘 (1) JDBC JDBC(Java Data Base Connection,java數據庫連接)是一種用于執行SQL語句的Java API,可以為多種關系數據庫提供統一訪問,它由一組用Java語言編寫的類和接口組成.JDBC提供了一種基準,據此可以構建更高級的工具和接口,使數據庫開發人員能夠編寫數據庫應用程序。 優點…

Vue3 + Echarts堆疊折線圖的tooltip不顯示問題

問題介紹 使用Echarts在Vue3Vite項目中繪制堆疊折線圖的的時候&#xff0c;tooltip總是不顯示&#xff0c;經過很長時間的排查和修改&#xff0c;最后發現是在使用上有錯誤導致的。 錯誤圖片展示 問題原因 由于Vue3底層使用proxy代理創建示例&#xff0c;使用其創建出來的實…

RDD 專項練習

RDD 專項練習 現有分數信息文件 scores.txt 班級ID 姓名 年齡 性別 科目 成績 12 張三 25 男 chinese 50 12 張三 25 男 math 60 12 張三 25 男 english 70 12 李四 20 男 chinese 50 12 李四 20 男 math 50 12 李四 20 男 english 50 12 王芳 19 女 chinese 70 12 王芳 19 女…

FPGA-Verilog-Vivado-軟件使用

這里寫目錄標題 1 軟件配置2 FPGA-7000使用2.1 運行啟動方式 1 軟件配置 編輯器綁定為Vscode&#xff0c;粘貼VS code運行文件的目錄&#xff0c;后綴參數保持不變&#xff1a; 如&#xff1a; D:/Users/xdwu/AppData/Local/Programs/Microsoft VS Code/Code.exe [file name]…

從技術到管理:你必須知道的七個轉變

在職業生涯的道路上&#xff0c;很多技術骨干會逐步轉向管理崗位。這不僅是職位的晉升&#xff0c;更是角色、思維和能力的全方位轉變。以下是七個關鍵的轉變&#xff0c;幫助技術人員順利完成這一跨越。 一、從個人貢獻者到團隊領導者的轉變 在技術崗位上&#xff0c;成功往…

(19)夾鉗(用于送貨)

文章目錄 前言 1 常見的抓手參數 2 參數說明 前言 Copter 支持許多不同的抓取器&#xff0c;這對送貨應用和落瓶很有用。 按照下面的鏈接&#xff08;或側邊欄&#xff09;&#xff0c;根據你的設置了解配置信息。 Electro Permanent Magnet v3 (EPMv3)Electro Permanent M…

bug記錄 qInstallMessageHandler的使用

QT (純C)項目 ‘Qxxx‘ file not found 和 編譯報錯問題(已解決)_qt頭文件file not found-CSDN博客 qInstallMessageHandler&#xff08;指針函數參數&#xff09; 需要靜態指針&#xff0c;這個函數 #include <iostream> #include "singleton.h" #include &…

Linux操作系統CentOS如何更換yum鏡像源

簡介 CentOS&#xff0c;是基于Red Hat Linux提供的可自由使用源代碼的企業級Linux發行版本&#xff1b;是一個穩定&#xff0c;可預測&#xff0c;可管理和可復制的免費企業級計算平臺。 下載地址: centos安裝包下載_開源鏡像站-阿里云 相關倉庫&#xff1a; CentOS過期源&…

職業教育人工智能實驗實訓室建設應用案例

隨著人工智能技術的快速發展&#xff0c;其在職業教育領域的應用逐漸深入。唯眾作為一家專注于教育技術領域的企業&#xff0c;積極響應國家關于人工智能教育的政策號召&#xff0c;通過建設人工智能實驗實訓室&#xff0c;為學生提供了一個實踐操作與創新思維相結合的學習平臺…

C++ STL iter_swap用法和實現

一&#xff1a;功能 交換兩個迭代器指向的元素值&#xff0c;一般用在模板中 二&#xff1a;使用 #include <vector> #include <iostream>template <typename It, typename Cond>requires std::forward_iterator<It> && std::indirectly_swa…

富格林:曝光糾正安全交易誤區

富格林指出&#xff0c;貴金屬投資是許多投資者追求資產多樣化和風險管理的重要途徑。然而&#xff0c;正如任何投資領域一樣&#xff0c;不少投資者也對貴金屬投資產生了一些誤區和錯誤觀念。但事實上&#xff0c;如果這種誤區一直伴隨著我們的交易進程&#xff0c;是很難做到…

34 超級數據查看器 關聯圖片

超級數據查看器app&#xff08;excel工具&#xff0c;數據庫軟件&#xff0c;表格app&#xff09; 關聯圖片講解 點擊 打開該講的視頻 點擊訪問app下載頁面 豌豆莢 下載地址 大家好&#xff0c;今天我們講一下超級數據查看器的關聯圖片功能 這個功能能讓表中的每一條信息&…

數據結構-散列表(hash table)

6.1 散列表的概念 散列表又叫哈希&#xff08;hash&#xff09;表&#xff0c;是根據鍵&#xff08;key&#xff09;直接訪問在內存存儲位置的值&#xff08;value&#xff09;的數據結構&#xff0c;由數組演化而來&#xff08;根據數組支持按照下標進行隨機訪問數據的特性&a…

windows腳本獲取 svn版本號

簡介 需要使用項目中svn的最新版本號 命令 set svnURL"URL" svn info %svnURL% | findstr "Revision:" > Version.txt for /f "token2 delims " %%i in (Version.txt) do set rev%%i echo %rev% pause

力扣爆刷第163天之TOP100五連刷81-85(回文鏈表、路徑和、最長重復子數組)

力扣爆刷第163天之TOP100五連刷81-85&#xff08;回文鏈表、路徑和、最長重復子數組&#xff09; 文章目錄 力扣爆刷第163天之TOP100五連刷81-85&#xff08;回文鏈表、路徑和、最長重復子數組&#xff09;一、234. 回文鏈表二、112. 路徑總和三、169. 多數元素四、662. 二叉樹…

洛谷 B4006 [GESP202406 四級] 寶箱

題目描述 小楊發現了 &#x1d45b; 個寶箱&#xff0c;其中第 &#x1d456; 個寶箱的價值是 &#x1d44e;&#x1d456;?。 小楊可以選擇一些寶箱放入背包并帶走&#xff0c;但是小楊的背包比較特殊&#xff0c;假設小楊選擇的寶箱中最大價值為 &#x1d465;&#xff0c…

next input代碼嘗試編寫

使用有限狀態機&#xff08;FSM&#xff09;可以使代碼結構更清晰&#xff0c;特別是處理復雜的狀態和過渡時。以下是如何根據你提供的步驟&#xff0c;用有限狀態機來實現自動校準和中斷觸發邏輯的示例代碼。 狀態定義 IDLE: 空閑狀態&#xff0c;等待數據輸入。CALIBRATING…

Python高級(三)_正則表達式

Python高級-正則表達式 第三章 正則表達式 在開發中會有大量的字符串處理工作,其中經常會涉及到字符串格式的校驗。 1、正則表達式概述 正則表達式,又稱正規表示式、正規表示法、正規表達式、規則表達式、常規表示法(英語:Regular Expression,在代碼中常簡寫為regex、…

PostgreSql中的JSON數據類型

PostgreSQL 提供了兩種 JSON 數據類型&#xff1a;JSON 以及 JSONB。這兩種類型主要的區別在于數據存儲格式&#xff0c;JSONB 使用二進制格式存儲數據&#xff0c;更易于處理。 PostgreSQL 推薦優先選擇 JSONB 數據類型。 兩種數據類型之間的區別&#xff1a; 功能JSONJSONB存…