力扣 滑動窗口題目總結

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

思路:
這道題主要用到思路是:滑動窗口

什么是滑動窗口?

其實就是一個隊列,比如例題中的 abcabcbb,進入這個隊列(窗口)為 abc 滿足題目要求,當再進入 a,隊列變成了 abca,這時候不滿足要求。所以,我們要移動這個隊列!

如何移動?

我們只要把隊列的左邊的元素移出就行了,直到滿足題目要求!

一直維持這樣的隊列,找出隊列出現最長的長度時候,求出解!

時間復雜度:O(n)

力扣官方題解說明:

方法2:滑動窗口法

思路:

我們使用兩個指針表示字符串中的某個子串(或窗口)的左右邊界,其中左指針代表著上文中「枚舉子串的起始位置」,而右指針即為上文中的 rk。

在每一步的操作中,我們會將左指針向右移動一格,表示 我們開始枚舉下一個字符作為起始位置,然后我們可以不斷地向右移動右指針,但需要保證這兩個指針對應的子串中沒有重復的字符。在移動結束后,這個子串就對應著 以左指針開始的,不包含重復字符的最長子串。我們記錄下這個子串的長度;

在枚舉結束后,我們找到的最長的子串的長度即為答案。

--判斷重復字符:

在上面的流程中,我們還需要使用一種數據結構來判斷 是否有重復的字符,常用的數據結構為哈希集合(即 C++ 中的 std::unordered_set,Java 中的 HashSet,Python 中的 set, JavaScript 中的 Set)。在左指針向右移動的時候,我們從哈希集合中移除一個字符,在右指針向右移動的時候,我們往哈希集合中添加一個字符。

至此,我們就完美解決了本題。

代碼如下:

class Solution {//這道題主要用到思路是:滑動窗口// 定義一個方法來計算字符串中無重復字符的最長子串長度public int lengthOfLongestSubstring(String s) {//定義一個哈希集合,記錄每個字符是否出現過(HashSet無序不可重復)Set<Character> occ = new HashSet<>(); //Charccter是Char的包裝類int n = s.length();//右指針,初始值為-1,相當于我們在字符串的左邊界的左側,還沒有開始移動int r = -1,res = 0;for(int i = 0; i < n; i ++){if(i != 0){//左指針向右移動一格,移除一個字符occ.remove(s.charAt(i-1));}//不斷移動右指針,直到遇到重復字符或者到達字符串末尾while(r + 1 < n && !occ.contains(s.charAt(r+1))){//沒到字符串末尾 && 不包含r+1-->將字符添加到集合中occ.add(s.charAt(r+1));//右指針右移++r;}//更新答案,取當前最大無重復子串的長度res = Math.max(res, r - i + 1);}// 返回結果,即最長無重復子串的長度return res;}
}

這段代碼使用了滑動窗口技術,通過移動兩個指針(左指針 i 和右指針 r)來尋找最長的無重復字符子串。具體操作如下:

  1. 初始化一個字符集合 occ 用于記錄當前窗口中包含的字符。
  2. 定義右指針 r?的初始值為 -1,表示它還沒有開始移動,并定義結果變量res?用于存儲最長子串的長度。
  3. 通過外層 for 循環移動左指針 i,逐個處理字符串中的字符。
  4. 如果左指針 i 不是在初始位置,則移除左指針前一個位置的字符 s.charAt(i - 1),以確保當前窗口只包含無重復字符。
  5. 使用 while 循環不斷右移右指針 r,擴展當前窗口,直到遇到重復字符或到達字符串末尾。每次右移時,將當前字符添加到集合 occ 中。
  6. 在每次擴展窗口后,更新結果 res?為當前窗口長度(r - i + 1)與之前最大長度中的較大值。
  7. 最終返回結果 res,即最長無重復字符子串的長度。

?補充知識點:

在Java中,Character 是一個包裝類(wrapper class),它封裝了一個基本類型 char 的值。Character 類提供了一些方法來操作字符數據類型。char 不同,Character 是一個類,可以用于泛型集合(如 SetList 等),因為這些集合只能包含對象,而不能包含基本數據類型。

下面是一些關于 Character 類的關鍵點:

  1. 封裝基本類型 char

    • char 是一個基本數據類型,表示單個16位Unicode字符。
    • Character 類將 char 封裝為對象,使其能夠在需要對象的上下文中使用。
  2. 創建 Character 對象

    可以通過構造器或自動裝箱(autoboxing)將 char 值轉換為 Character 對象。
char ch = 'a';
Character characterObject = new Character(ch); // 使用構造器
Character characterObject2 = ch; // 自動裝箱

?????3.常用方法

  • Character 類提供了許多實用方法來處理字符。例如:
  • Character.isDigit(char ch): 檢查字符是否為數字。
  • Character.isLetter(char ch): 檢查字符是否為字母。
  • Character.toUpperCase(char ch): 將字符轉換為大寫。
  • Character.toLowerCase(char ch): 將字符轉換為小寫。

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

?

class Solution {// 定義一個方法來查找字符串 s 中所有是字符串 p 的字母異位詞的子串的起始索引public List<Integer> findAnagrams(String s, String p) {// 獲取字符串 s 和 p 的長度int n = s.length(), m = p.length();// 結果列表,用于存儲所有符合條件的起始索引List<Integer> res = new ArrayList<>();// 如果 s 的長度小于 p 的長度,直接返回空列表if(n < m) return res;// 定義兩個數組,用于記錄 p 和 s 當前窗口中字符的頻率int[] pCnt = new int[26];int[] sCnt = new int[26];// 初始化頻率數組,將 p 和 s 前 m 個字符的頻率記錄到各自的數組中for(int i = 0; i < m; i++){pCnt[p.charAt(i) - 'a']++;sCnt[s.charAt(i) - 'a']++;}// 檢查初始窗口(s 的前 m 個字符)是否與 p 匹配,如果匹配,將索引 0 加入結果列表if(Arrays.equals(sCnt, pCnt)){res.add(0);}// 遍歷字符串 s,從索引 m 開始,每次向右滑動一個字符for(int i = m; i < n; i++){// 移除左邊界字符的頻率(滑動窗口左移)sCnt[s.charAt(i - m) - 'a']--;// 添加右邊界字符的頻率(滑動窗口右移)sCnt[s.charAt(i) - 'a']++;// 檢查當前窗口是否與 p 匹配,如果匹配,將起始索引加入結果列表if(Arrays.equals(sCnt, pCnt)){res.add(i - m + 1);}}// 返回結果列表return res;}
}
  1. 初始化和邊界檢查

    • 獲取 sp 的長度。
    • 如果 s 的長度小于 p 的長度,直接返回空列表,因為不可能有異位詞。
  2. 頻率數組初始化

    • 使用兩個大小為 26 的數組 pCntsCnt 分別記錄 ps 當前窗口中字符的頻率。
    • 初始化頻率數組,記錄 psm 個字符(p 的長度)的頻率。
  3. 初始窗口匹配檢查

    • 檢查 s 的前 m 個字符是否與 p 匹配,如果匹配,將索引 0 加入結果列表。
  4. 滑動窗口遍歷

    • 從索引 m 開始遍歷 s,每次滑動窗口右移一個字符:
      • 減少左邊界字符的頻率(移出窗口)。
      • 增加右邊界字符的頻率(加入窗口)。
      • 檢查當前窗口是否與 p 匹配,如果匹配,將起始索引加入結果列表。
  5. 返回結果

    • 返回包含所有符合條件的起始索引的結果列表。

代碼深度解釋:

im 開始遍歷到 n-1 時,代表滑動窗口的右邊界每次右移一個字符,這兩行代碼分別是在這個過程中執行的操作。

  1. sCnt[s.charAt(i - m) - 'a']--;:這行代碼是為了移除左邊界字符的頻率。在滑動窗口右移時,窗口的左邊界向右移動一個字符,因此需要將移出窗口的左邊界字符在 sCnt 數組中的計數減去 1。

  2. sCnt[s.charAt(i) - 'a']++;:這行代碼是為了添加右邊界字符的頻率。在滑動窗口右移時,窗口的右邊界向右移動一個字符,因此需要將新加入窗口的右邊界字符在 sCnt 數組中的計數加上 1。

這兩步操作保證了每次窗口的頻率數組 sCnt 都能正確地反映當前窗口中字符的頻率情況,以便后續比較是否與 p 的頻率數組 pCnt 相同,從而判斷是否滿足異位詞的條件。

class Solution {// 定義一個方法來查找字符串 s 中所有是字符串 p 的字母異位詞的子串的起始索引public List<Integer> findAnagrams(String s, String p) {// 獲取字符串 s 和 p 的長度int n = s.length(), m = p.length();// 結果列表,用于存儲所有符合條件的起始索引List<Integer> res = new ArrayList<>();// 如果 s 的長度小于 p 的長度,直接返回空列表if (n < m) return res;// 定義兩個數組,用于記錄 p 和 s 當前窗口中字符的頻率int[] pCnt = new int[26];int[] sCnt = new int[26];// 初始化 p 的頻率數組,將 p 的每個字符的頻率記錄到 pCnt 數組中for (int i = 0; i < m; i++) {pCnt[p.charAt(i) - 'a']++;}// 定義左指針,初始值為 0int left = 0;// 遍歷字符串 s,每次右指針右移一個字符for (int right = 0; right < n; right++) {// 獲取右指針當前字符在字母表中的索引int curRight = s.charAt(right) - 'a';// 增加當前右指針字符在 sCnt 數組中的頻率sCnt[curRight]++;// 如果當前右指針字符的頻率超過了 p 中該字符的頻率,需要縮小窗口while (sCnt[curRight] > pCnt[curRight]) {// 獲取左指針當前字符在字母表中的索引int curLeft = s.charAt(left) - 'a';// 減少當前左指針字符在 sCnt 數組中的頻率sCnt[curLeft]--;// 左指針右移一格left++;}// 如果當前窗口的長度等于 p 的長度,說明找到了一個異位詞if (right - left + 1 == m) {// 將當前窗口的起始索引加入結果列表res.add(left);}}// 返回結果列表return res;}
}

這段代碼使用了滑動窗口和字符頻率計數技術來查找字符串 s 中所有是字符串 p 的字母異位詞的子串的起始索引。具體操作如下:

  1. 初始化和邊界檢查

    • 獲取 sp 的長度。
    • 如果 s 的長度小于 p 的長度,直接返回空列表,因為不可能有異位詞。
  2. 頻率數組初始化

    • 使用一個大小為 26 的數組 pCnt 記錄 p 中每個字符的頻率。
    • 使用一個大小為 26 的數組 sCnt 來記錄當前滑動窗口中字符的頻率。
  3. 滑動窗口遍歷

    • 使用兩個指針 leftright 表示當前滑動窗口的左右邊界。
    • 右指針 right 從 0 開始遍歷 s,每次右移一個字符,將該字符在 sCnt 數組中的頻率加 1。
    • 如果當前字符的頻率超過了 p 中該字符的頻率,進入 while 循環,通過移動左指針 left 來縮小窗口,直到當前字符的頻率不超過 p 中該字符的頻率為止。
    • 如果當前窗口的長度等于 p 的長度,說明找到了一個異位詞,將窗口的起始索引 left 加入結果列表。
  4. 返回結果

    • 返回包含所有符合條件的起始索引的結果列表。

?

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

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

相關文章

牛客NC334 字典序第K小【困難 10叉樹 Java/Go/PHP/C++】,力扣 440. 字典序的第K小數字

題目 題目鏈接&#xff1a; https://www.nowcoder.com/practice/670c2bda374241d7ae06ade60de33e8b https://leetcode.cn/problems/k-th-smallest-in-lexicographical-order/description/ 本答案核心 10叉樹, 數學規律Java代碼 import java.util.*;public class Solution {…

大模型的靈魂解讀:Anthropic AI的Claude3 Sonnet可解釋性研究

大模型技術論文不斷&#xff0c;每個月總會新增上千篇。本專欄精選論文重點解讀&#xff0c;主題還是圍繞著行業實踐和工程量產。若在某個環節出現卡點&#xff0c;可以回到大模型必備腔調重新閱讀。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;則提供了大模型領域最新技…

Vue集成Iframe

一、應用場景&#xff0c;為什么要集成Iframe&#xff1f; 1、龐大項目拆分后&#xff0c;便于管理和部署&#xff0c;用集成Iframe的方法合并 2、避免功能重復開發&#xff0c;共用模塊可單獨開發為一個項目&#xff0c;既可獨立部署&#xff0c;也可集成到中臺系統 二、集成…

[算法][前綴和] [leetcode]724. 尋找數組的中心下標

題目地址 https://leetcode.cn/problems/find-pivot-index/description/ 題目描述 代碼 class Solution {public int pivotIndex(int[] nums) {int total Arrays.stream(nums).sum();//前綴和int prefixSum 0;int len nums.length;for(int i 0;i<len;i){if (i-1>0){p…

小豬APP分發:一站式托管服務,輕松玩轉應用市場

在當今移動應用爆炸式增長的時代&#xff0c;開發者們面臨的挑戰不再僅限于創意的火花和代碼的實現&#xff0c;更在于如何讓精心打造的應用快速觸達廣大用戶。這正是小豬APP分發www.appzhu.net應運而生的背景——作為一個全面、高效的APP托管服務分發平臺&#xff0c;它為開發…

基于PHP的物業管理的設計與實現

第1章 緒論... 1 1.1 研究背景與意義... 1 1.2 國內外發展現狀... 2 第2章 關鍵技術介紹... 3 2.1 PHP語言... 3 2.2 MySQL數據庫... 3 2.3 Zend框架... 4 2.4 B/S架構... 4 第3章 系統需求分析... 5 3.1 可行性分析... 5 3.1.1 技術可行性分析... 5 3.1.2 經濟可行…

解決Java中的IllegalArgumentException異常的正確方法

解決Java中的IllegalArgumentException異常的正確方法 引言 在Java編程中&#xff0c;IllegalArgumentException是一個常見的運行時異常&#xff0c;它通常在方法接收到不合法或不適當的參數時拋出。這篇文章將詳細介紹IllegalArgumentException異常的原因、如何診斷以及解決…

金職優學:分析央國企面試如何通關?

在當今競爭激烈的就業市場中&#xff0c;中央和國有企業&#xff08;以下簡稱“央國企”&#xff09;的面試機會對求職者來說是非常有吸引力的。這些企業通常擁有穩定的發展前景、良好的薪酬福利和廣闊的職業發展空間。但是&#xff0c;要想成功通過央國企的面試&#xff0c;求…

探索Python編程世界:從基礎到實戰

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、Python語言簡介與動態特性 代碼示例&#xff1a;動態類型與變量命名 二、Python應用領…

vue 表格表頭展示不下,顯示。。。;鼠標懸浮展示全部

vue 表格表頭展示不下&#xff0c;顯示。。。&#xff1b;鼠標懸浮展示全部 <templateslot-scope"scope"slot"header"><span:title"臨時證券類型"style"white-space:nowrap">{{ 臨時證券類型 }}</span></templa…

Terminal Web終端基礎(Web IDE 技術探索 二)

Terminal是web終端技術&#xff0c;類似cmd命令窗口&#xff0c;Webcontainer 中推薦使用的是Xterm.js&#xff0c;這里就不細說Xterm.js 的使用了&#xff0c;我們使用第三方庫來實現&#xff08;原生確實有點難用&#xff09;。 vue-web-terminal 一個由 Vue 構建的支持多內容…

【設計模式】JAVA Design Patterns——Bytecode(字節碼模式)

&#x1f50d;目的 允許編碼行為作為虛擬機的指令 &#x1f50d;解釋 真實世界例子 一個團隊正在開發一款新的巫師對戰游戲。巫師的行為需要經過精心的調整和上百次的游玩測試。每次當游戲設計師想改變巫師行為時都讓程序員去修改代碼這是不妥的&#xff0c;所以巫師行為以數據…

環形鏈表Ⅱ-力扣

第一種解法時哈希表&#xff0c;set在使用insert插入時&#xff0c;會返回一個pair&#xff0c;如果pair的值為0&#xff0c;則插入失敗&#xff0c;那么返回這個插入失敗的節點&#xff0c;就是入環的第一個節點&#xff0c;代碼如下&#xff1a; /*** Definition for singly…

導航【面試準備】

導航【面試準備】 前言版權導航【面試準備】面經準備 最后 前言 2024-5-20 12:47:11 以下內容源自《【面試準備】》 僅供學習交流使用 版權 禁止其他平臺發布時刪除以下此話 本文首次發布于CSDN平臺 作者是CSDN日星月云 博客主頁是https://jsss-1.blog.csdn.net 禁止其他平…

AcW木棒-XMUOJ恢復破碎的符咒木牌-DFS與剪枝

題目 思路 話不多說&#xff0c;直接上代碼 代碼 /* AcW木棒-XMUOJ恢復破碎的符咒木牌 搜索順序&#xff1a;從小到大枚舉最終的長度 len從前往后依次拼每根長度為len的木棍 優化&#xff1a; 1.優化搜索順序&#xff1a;優先選擇深度短的來搜索&#xff0c;故從大到小去枚…

【系統分析師】WEB開發-案例

文章目錄 1、WEB開發涉及內容1.1 負載均衡技術1.2 數據庫讀寫分離1.3 緩存 緩解讀庫壓力1.4 CDN1.5 WEB應用服務器1.6 整體結構1.6 相關技術1.6.1 redis相關(集群、持久化等)1.6.2 XML與JSON1.6.3 REST1.6.4 響應式web設計1.6.5 關于中臺1.6.6 Web系統分層 1、WEB開發涉及內容 …

Python--面向對象

面向對象?? 1. 面向對象和面向過程思想 面向對象和面向過程都是一種編程思想,就是解決問題的思路 面向過程&#xff1a;POP(Procedure Oriented Programming)面向過程語言代表是c語言面向對象&#xff1a;OOP(Object Oriented Programming)常見的面向對象語言包括:java c g…

19c數據庫19.9以下dg切換打開hang住問題

原主庫發起切換請求&#xff0c;原主庫正常切換數據庫角色&#xff0c;但原從庫無法正常打開數據庫&#xff0c;嘗試關閉重啟&#xff0c;依舊無法解決問題。 查看切換過程中原從庫數據庫后臺日志&#xff0c;發現數據庫一直不斷重試清理 SRLs&#xff0c; 后臺alert日志&…

力扣HOT100 - 21. 合并兩個有序鏈表

解題思路&#xff1a; class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode dum new ListNode(0), cur dum;while (list1 ! null && list2 ! null) {if (list1.val < list2.val) {cur.next list1;list1 list1.next;} els…

基本IO接口

引入 基本輸入接口 示例1 示例2&#xff1a;有數據保持能力的外設 #RD端由in指令控制&#xff1a;將數據由端口傳輸到CPU內存中 #CS244信號由譯碼電路實現 示例3&#xff1a; a)圖中由于輸出端口6有連接到端口1&#xff0c;當開關與端點1閉合時期間&#xff0c;仍能維持3端口…