【滑動窗口】C++高效解決子數組問題

個人主頁 : zxctscl
專欄 【C++】、 【C語言】、 【Linux】、 【數據結構】、 【算法】
如有轉載請先通知

文章目錄

  • 前言
  • 1 209. 長度最小的子數組
    • 1.1 分析
    • 1.2 代碼
  • 2 3. 無重復字符的最長子串
    • 2.1 分析
    • 2.2 代碼
  • 3 1004. 最大連續1的個數 III
    • 3.1 分析
    • 3.2 代碼
  • 4 1658. 將 x 減到 0 的最小操作數
    • 4.1 分析
    • 4.2 代碼
  • 5 904. 水果成籃
    • 5.1 分析
    • 5.2 代碼
  • 6 438. 找到字符串中所有字母異位詞
    • 6.1 分析
    • 6.2 代碼
  • 7 30. 串聯所有單詞的子串
    • 7.1 分析
    • 7.2 代碼
  • 8 76. 最小覆蓋子串
    • 8.1 分析
    • 8.2 代碼

前言

1 209. 長度最小的子數組

在這里插入圖片描述

1.1 分析

暴力枚舉出所有的子數組和,發現可以利用雙指針來解決。
這里雙指針是同向的,就能優化為滑動窗口。
(1)先初始化left和right,用left和right來標記這個窗口的左右區間
(2)進窗口
(3)判斷決定是否出窗口

1.2 代碼

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums){int n=nums.size();int sum=0,len=INT_MAX;for(int left=0,right=0;right<n;right++){sum+=nums[right];while(sum>=target){len=min(len,right-left+1);sum-=nums[left++];}}return len==INT_MAX?0:len;}
};

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

在這里插入圖片描述

2.1 分析

暴力枚舉利用雙指針加哈希表:
left在起始位置,right遍歷,當字符不在哈希表里,就添加;當字符在時候,right就停止遍歷,把此時的字符長度更新一下;再把left移動到與right遍歷到相同字符的那個位置的后面一個,然后right再繼續移動。
在這里插入圖片描述
使用滑動窗口來實現:

(1)先初始化left和right,用left和right來標記這個窗口的左右區間
(2)進窗口,讓字符進入哈希表
(3)判斷:當窗口內出現重復字符出窗口,再從哈希表中刪除該字符。
再更新長度

2.2 代碼

class Solution 
{
public:int lengthOfLongestSubstring(string s) {int hash[128]={0};//數組模擬哈希表int n=s.size();int ret=0;for(int left=0,right=0;right<n;right++){hash[s[right]]++;//進窗口while(hash[s[right]]>1)//判斷{hash[s[left++]]--;//出窗口}ret=max(ret,right-left+1);}return ret;}
};

3 1004. 最大連續1的個數 III

在這里插入圖片描述

3.1 分析

只要翻轉的0個數小于等于k就行。
如果按照題目要求翻轉,是比較麻煩的,但可以等價處理為:找一個區間滿足0的次數不超過k就行。
也就是找出最長子數組,這個子數組的0不超過k個
解法一:暴力枚舉所有子數組,加上一個計數器zero
優化一下

固定left,right向后移動,right遇到0統計一個計數器,計數器等于3時候,停止枚舉,就是這個區間最優解。

在這里插入圖片描述
利用滑動窗口來解決問題:

  1. 先定義兩個指針left=0,right=0
  2. 進窗口,如果right遇到1,無視;遇到0,zero+1
  3. 判斷:zero>k 就 出窗口
    判斷完后更新結果

3.2 代碼

class Solution {
public:int longestOnes(vector<int>& nums, int k) {int ret=0;for(int left=0,right=0,zero=0;right<nums.size();right++){if(nums[right]==0)zero++;while(zero>k)if(nums[left++]==0)zero--;   ret=max(ret,right-left+1);}return ret;}
};

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

在這里插入圖片描述

4.1 分析

發現既有左邊刪除,又有右邊的的,不好操作,此時可以找一個連續區域,恰好所有元素的和(sum)等于sum-x

  1. 先定義兩個指針left=0,right=0
  2. 進窗口,sum+=nums[right]
  3. 判斷:sum>target
    出窗口:sum-=nums[left]
    當sum==target判斷完后更新結果

4.2 代碼

class Solution {
public:int minOperations(vector<int>& nums, int x) {int sum=0;for(int a:nums)sum+=a;int target=sum-x;if(target<0)return -1;int ret=-1;for(int left=0,right=0,tmp=0;right<nums.size();right++){tmp+=nums[right];while(tmp>target){tmp-=nums[left++];}if(tmp==target)ret=max(ret,right-left+1);}if(ret==-1)return -1;else{return nums.size()-ret;}}
};

5 904. 水果成籃

在這里插入圖片描述

5.1 分析

題目意思就是:找出一個最長子數組,子數組中不超過兩種類型的水果。

解法一:暴力枚舉+哈希表:從某一個位置開始,建立一個哈希表,暴力枚舉時候,遍歷一個放哈希表一個,當表中數據超過2時候,就出現了多余水果,前面的區間就是最優解。

優化:固定一個位置left,right遍歷數組放在哈希表中,直到某一個位置,right再向右遍歷時候,水果種類就超過2,此時這段區間就是最優解。此時,當left向后移動一位時,種類數目(kinds)可能會出現兩種情況:(1)kinds不變,那么right也不變;(2)kinds變小,此時right就可以向右移動

解法二:滑動窗口

  1. 先定義兩個指針left=0,right=0
  2. 進窗口,遍歷數組放哈希表里,哈希表里面放水果種類及對應數量
  3. 判斷:如果哈希表長度大于2而且它對應數量為0時候就出窗口
    更新結果
    在這里插入圖片描述

5.2 代碼

class Solution {
public:int totalFruit(vector<int>& fruits){int hash[100001]={0};int ret=0;for(int left=0,right=0,kinds=0;right<fruits.size();right++){if(hash[fruits[right]]==0)kinds++;hash[fruits[right]]++;while(kinds>2){hash[fruits[left]]--;if(hash[fruits[left]]==0)kinds--;left++;}ret=max(ret,right-left+1);}return ret;}
};

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

在這里插入圖片描述

6.1 分析

如何快速判斷兩個字符串是否是異位詞?
兩個字符串的構成是一樣的,利用哈希表,遍歷兩個字符串分別放在哈希表中,對比兩個哈希表中字符出現的個數是否相等就行,相等就是,反之就不是。

算法:
暴力+哈希表
把p字符串先放入哈希表中,再到s中找相等長度的區間子串放在另一個哈希表中,比較一個,相等就把起始位置放在結果中。

當s中與p等長區間中比較后,不是異位詞,此時就把s放在哈希表中的第一個字符刪除,再加上區間長度下一個位置字符就行。
在這里插入圖片描述

p長度為m,hash1記錄p的字符情況,hash2記錄s中一段區間的字符情況
滑動窗口+哈希表

  1. 先定義兩個指針left=0,right=0
  2. 進窗口,(哈希表遍歷s)hash2[in]++
  3. 判斷:right-left+1>m,就出窗口,再hash1[out]–(對應s中的字符得刪除)

當兩個哈希表里面存在信息是否一致時候,就更新結果
在這里插入圖片描述
優化:更新判斷條件
利用變量count來統計窗口中有效字符的個數
right遍歷時候,c加入哈希表2中,與hash1中c個數相比較,都是1,此時count=1
right繼續向后面移動,遇到c加入hash2中,這個時候hash2中c=2,,比hash1中c=1大,這個時候count不更新
right繼續向后移動,b放入hash2中,比較hash1中b=1,此時count=2,而且s遍歷的區間長度等于p的長度,此時有效字符個數count=2不等于p的長度;
right繼續右移,這是區間長度大于p的,left就右移,a放到哈希表2中a=1,count=3,刪除c(hash2中c=2,刪除的這個c是無效字符),hash2中c=1;
在這里插入圖片描述
進窗口:進窗口后比較hash2[in]<=hash1[in]此時count++;
出窗口:出去前 hash2[out]<=hash1[out]此時count–;
更新結果:count=m

6.2 代碼

class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> ret;int hash1[26]={0};//統計pfor(auto x:p)hash1[x-'a']++;int hash2[26]={0};//sint m=p.size();for(int left=0,right=0,count=0;right<s.size();right++){char in=s[right];hash2[in-'a']++;if(hash2[in-'a']<=hash1[in-'a'])count++;if(right-left+1>m){char out=s[left++];if(hash2[out-'a']<=hash1[out-'a'])count--;hash2[out-'a']--;}if(count==m)ret.push_back(left);}return ret;}
};

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

在這里插入圖片描述

7.1 分析

與上面串聯所有單詞的子串類似,只不過把字符換成字符串,解法類似。
把題目給的words中的字符串看做一個一個整體,像下面這樣
在這里插入圖片描述

與上面不同的是:
(1)哈希表:不能向上面一樣用數組來實現,這里存字符串,得用unordered_map<string,int> hash
(2)left與right指針的移動:移動的步長是單詞的長度(len)
(3)滑動窗口指向的次數:單詞可能是從s的第一個位置開始劃分,也可能是第二個位置,也可能是第三個位置:
在這里插入圖片描述
滑動窗口執行len次

7.2 代碼

class Solution {
public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> ret;unordered_map<string,int> hash1;for(auto& x:words)hash1[x]++;int len=words[0].size(),m=words.size();for(int i=0;i<len;i++){unordered_map<string,int> hash2;for(int left=i,right=i,count=0;right+len<=s.size();right+=len){string in=s.substr(right,len);//進窗口+維護counthash2[in]++;if(hash2[in]<=hash1[in])count++;//判斷if(right-left+1>len*m){//出窗口+維護countstring 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 76. 最小覆蓋子串

在這里插入圖片描述

8.1 分析

與串聯所有單詞的子串類似,

解法一:暴力枚舉+哈希表
在連續區間中找符合要求的ABC出現次數
在這里插入圖片描述
在符合連續區間中,left右移right會出現兩種情況
在這里插入圖片描述

解法二:滑動窗口

  1. 先定義兩個指針left=0,right=0
  2. 進窗口,hash2[in]++
  3. 判斷:對比一下hash2有效字符大于等于hash1有效字符就更新結果起始位置,最短長度;再出窗口,hash2[out]–

優化:利用變量count來統計窗口中有效字符的種類
(1).進窗口 進之后當hash2[in]==hash1[in]此時count++
(2) 出窗口 出之前,當hash2[out]==hash1[out]count--
(3)判斷 count==hash.size()

8.2 代碼

class Solution {
public:string minWindow(string s, string t) {int hash1[128]={0};int kinds=0;//統計有效字符有多少種for(auto& x:t){if(hash1[x]==0) kinds++;hash1[x]++;}int hash2[128]={0};int minlen=INT_MAX,begin=-1;for(int left=0,right=0,count=0;right<s.size();right++){char in=s[right];hash2[in]++;if(hash2[in]==hash1[in])count++;//進窗口+維護countwhile(kinds==count){if(right-left+1<minlen){minlen=right-left+1;begin=left;}char out=s[left++];if(hash2[out]--==hash1[out])count--;}}if(begin==-1)return "";else return s.substr(begin,minlen);}
};

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

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

相關文章

[rStar] 搜索代理(MCTS/束搜索)

第2章&#xff1a;搜索代理(MCTS/束搜索) 歡迎回到rStar 在前一章中&#xff0c;我們學習了求解協調器&#xff0c;它就像是解決數學問題的項目經理。 它組織整個過程&#xff0c;但本身并不進行"思考"&#xff0c;而是將這項工作委托給其專家團隊。 今天&#x…

Electron 核心模塊速查表

為了更全面地覆蓋常用 API&#xff0c;以下表格補充了更多實用方法和場景化示例&#xff0c;同時保持格式清晰易讀。 一、主進程模塊 模塊名核心用途關鍵用法 示例注意事項app應用生命周期管理? 退出應用&#xff1a;app.quit()? 重啟應用&#xff1a;app.relaunch() 后需…

Qt C++ 圖形繪制完全指南:從基礎到進階實戰

Qt C 圖形繪制完全指南&#xff1a;從基礎到進階實戰 前言 Qt框架提供了強大的2D圖形繪制能力&#xff0c;通過QPainter類及其相關組件&#xff0c;開發者可以輕松實現各種復雜的圖形繪制需求。本文將系統介紹Qt圖形繪制的核心技術&#xff0c;并通過實例代碼演示各種繪制技巧…

二分搜索邊界問題

在使用二分搜索的時候&#xff0c;更新條件不總是相同&#xff0c;雖然說使用bS目的就是為了target&#xff0c;但也有如下幾種情況&#xff1a;求第一個target的索引求第一個>target的索引求第一個>target的索引求最后一個target的索引求最后一個<target的索引求最后…

【springboot+vue3】博客論壇管理系統(源碼+文檔+調試+基礎修改+答疑)

目錄 一、整體目錄&#xff1a; 項目包含源碼、調試、修改教程、調試教程、講解視頻、開發文檔&#xff08;項目摘要、前言、技術介紹、可行性分析、流程圖、結構圖、ER屬性圖、數據庫表結構信息、功能介紹、測試致謝等約1萬字&#xff09; 二、運行截圖 三、代碼部分&…

20250907_梳理異地備份每日自動巡檢Python腳本邏輯流程+安裝Python+PyCharm+配置自動運行

一、邏輯流程(autocheckbackup.py在做什么) 1.連接Linux服務器 用 paramiko 登錄你配置的 Linux 服務器(10.1.3.15, 10.1.3.26),進入指定目錄(如 /home, /backup/mes),遞歸列出文件。 采集到的信息:服務器IP、目錄、數據庫名稱、文件名、大小、修改時間。 2.連接Wind…

terraform-state詳解

一、Treeaform-state的作用 Terraform-state是指Terroform的狀態&#xff0c;是terraform不可缺少的生命周期元素。本質上來講&#xff0c;terraform狀態是你的基礎設施配置的元數據存儲庫&#xff0c;terraform會把它管理的資源狀態保存在一個狀態文件里。 默認情況下&#xf…

四、kubernetes 1.29 之 Pod 生命周期

一、概述當容器與 pause 容器共享網絡&#xff08;Network&#xff09;、IPC&#xff08;進程間通信&#xff09;和 PID&#xff08;進程命名空間&#xff09;后&#xff0c;二者形成了一種緊密的 "共享命名空間" 關系&#xff0c;共同構成了 Kubernetes 中 "Po…

AI與環保:禮貌用語背后的能源挑戰與解決方案

程序員的技術管理推薦閱讀 窄化效應&#xff1a;程序員與管理者的隱形情緒陷阱 從“激勵”到“保健”&#xff1a;80后與90后程序員&#xff0c;到底想要什么&#xff1f; 從“激勵”到“保健”&#xff1a;80后與90后程序員&#xff0c;到底想要什么&#xff1f; 場景引入&…

OpenCV C++ 特征提取:從角點檢測到對象識別

特征提取是計算機視覺的核心技術,通過識別圖像中具有代表性的關鍵點及其描述信息,實現圖像匹配、對象識別、姿態估計等高級任務。本章將系統講解從基礎的圖像金字塔、角點檢測,到復雜的 ORB 和 SIFT 特征提取與匹配,最終實現基于特征的對象檢測完整流程。 一、圖像金字塔 …

Codeforces Round 1049 (Div. 2) D題題解記錄

大致題意&#xff1a;給定nnn個區間(li,ri)(l_i,r_i)(li?,ri?)。每次選取兩個尚未被標記的區間(l1,r1)(l_1,r_1)(l1?,r1?)與(l2,r2)(l_2,r_2)(l2?,r2?)&#xff0c;使得他們均被標記&#xff0c;同時可以任選x∈[l1,r1]&#xff0c;y∈[l2,r2]x\in[l_1,r_1]&#xff0c;y…

《WINDOWS 環境下32位匯編語言程序設計》第15章 注冊表和INI文件

15.1 注冊表和INI文件簡介在一個操作系統中&#xff0c;無論是操作系統本身還是運行于其中的大部分應用程序&#xff0c;都需要使用某種方式保存配置信息。在DOS系統中&#xff0c;配置信息往往是軟件的開發者根據自己的喜好用各種途徑加以保存的&#xff0c;比如在磁盤上面寫一…

JDK 17、OpenJDK 17、Oracle JDK 17 的說明

Java生態系統的核心概念&#xff1a;簡單來說&#xff1a;JDK 17 是一個標準規范&#xff0c;定義了Java開發工具包第17個長期支持版應該包含什么功能。openjdk-17-jdk 是一個具體的實現&#xff0c;是遵循上述規范、由OpenJDK社區提供的開源軟件包。下面我們通過一個表格和詳細…

手寫MyBatis第58彈:如何優雅輸出可執行的SQL語句--深入理解MyBatis日志機制:

&#x1f942;(???)您的點贊&#x1f44d;?評論&#x1f4dd;?收藏?是作者創作的最大動力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;點贊&#x1f44d;收藏??留言&#x1f4dd;歡迎留言討論 &#x1f525;&#x1f525;&…

Spring Boot 監控實戰:集成 Prometheus 與 Grafana,打造全方位監控體系

前言 在當今微服務架構盛行的時代&#xff0c;應用程序的監控變得尤為重要。Spring Boot 作為廣泛使用的微服務框架&#xff0c;其監控需求也日益增加。Prometheus 和 Grafana 作為開源監控領域的佼佼者&#xff0c;為 Spring Boot 應用提供了強大的監控能力。本文將詳細介紹如…

JS中的多線程——Web Worker

眾所周知&#xff0c;JavaScript 是單線程運行的&#xff08;至于為什么是單線程可以看一下這篇文章——事件循環機制&#xff09;&#xff0c;當瀏覽器主線程被大量計算任務阻塞時&#xff0c;頁面就會出現明顯的卡頓現象。Web Worker 提供了在獨立線程中運行 JavaScript 的能…

【SQL注入】延時盲注

sleep(n)??: 核心延時函數。使數據庫程序暫停 n秒。??if(condition, true_expr, false_expr)??: 條件判斷函數。如果 condition為真&#xff0c;執行 true_expr&#xff0c;否則執行 false_expr。??用于將延時與判斷條件綁定??。??mid(a, b, c)??: 字符串截取函數…

IntelliJ IDEA 2025.1 Java Stream Debugger 快速使用指南

1. 功能概覽 Java Stream Debugger 提供 Trace Current Stream Chain 功能&#xff0c;用來在調試時分析和可視化 Stream 操作鏈。 主要用途&#xff1a; 在運行時查看流操作鏈的每一步輸出找出 map/filter 等操作的問題避免手動加 peek() 打印調試2. 使用入口 在 IDEA 2025.1 …

ARM-指令集全解析:從基礎到高階應用

一、ARM 指令集體系結構版本ARM 公司定義了多個指令集版本&#xff1a;ARMv1&#xff1a;原型機 ARM1&#xff0c;沒有用于商業產品。ARMv2&#xff1a;擴展 V1&#xff0c;包含 32 位乘法指令和協處理器指令。ARMv3&#xff1a;第一個微處理器 ARM6 核心&#xff0c;支持 Cach…

第3講 機器學習入門指南

近年來&#xff0c;隨著企業和個人生成的數據量呈指數級增長&#xff0c;機器學習已成為日益重要的技術領域。從自動駕駛汽車到流媒體平臺的個性化推薦&#xff0c;機器學習算法已廣泛應用于各個場景。讓我們深入解析機器學習的核心要義。3.1 機器學習定義機器學習是人工智能的…