雙指針與滑動窗口算法精講:從原理到高頻面試題實戰

引言:算法選擇的十字路口

????????在算法面試中,雙指針和滑動窗口如同兩把瑞士軍刀,能高效解決80%以上的數組和字符串問題。本文將深入解析這兩種技術的核心差異,結合力扣高頻題目,提供可直接復用的代碼。

一、算法核心思想解析

1. 雙指針技術

????????雙指針算法是通過維護?兩個指針變量?(通常為數組/鏈表索引)協同遍歷數據結構的高效策略,主要用于優化暴力解法的時空復雜度。

?三種經典模式?:

  • ?對撞指針?:首尾指針向中間收斂(如三數之和)
  • ?快慢指針?:同向移動但速度不同(如環形鏈表檢測)
  • ?滑動窗口?:動態維護子區間(特殊雙指針實現)

2. 滑動窗口技術

????????作為雙指針的特殊形式,滑動窗口具有以下特點:

  • 兩個指針?同向移動?且?維護一個連續區間
  • 通過窗口擴張/收縮動態調整解空間

3. 算法特性對比

特性

雙指針算法

滑動窗口算法

?指針移動方向?

可對撞/同向

嚴格同向移動

?數據要求?

常需排序

原始數據即可

?時間復雜度?

O(n)~O(n2)

O(n)

?典型問題?

有序數組組合問題

子串/子數組最優解

?狀態維護?

通常不需要

需要哈希表記錄狀態

二、高頻面試題分類精講

1. 雙指針經典題型三數之和(LeetCode 15

解題思路

1. 暴力解法(不推薦)

最直觀的方法是三重循環遍歷所有可能的三元組,時間復雜度為O(n3),效率太低。

2. 排序 + 雙指針法(推薦)

?步驟如下:?

  1. ?排序數組?:首先將數組排序,這樣可以利用有序性來優化搜索
  2. ?固定一個數?:遍歷數組,將當前元素作為第一個數
  3. ?雙指針搜索?:在當前元素后面的部分使用雙指針(左指針從當前元素后一位開始,右指針從數組末尾開始)尋找另外兩個數
  4. ?去重處理?:跳過重復的元素以避免重復解

?時間復雜度?:O(n2)(排序O(nlogn) + 雙指針遍歷O(n2))

public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> result = new ArrayList<>();int length = nums.length;if (nums == null || length < 3) {return result;}Arrays.sort(nums);  // 關鍵步驟:排序for (int i =0; i < length; i++) {// 需要和上一次枚舉的數不相同if (i > 0 && nums[i] == nums[i - 1]) {continue;}int left = i+1;int right = length - 1;int target = -nums[i]; // nums[left] + nums[right] = targetwhile(left < right) {int sum = nums[left] + nums[right];if (sum == target) {result.add(Arrays.asList(nums[i], nums[left], nums[right]));// 跳過重復的left和rightwhile (left < right && nums[left] == nums[left + 1]) left++;while (left < right && nums[right] == nums[right - 1]) right--;left++;right--;} else if (sum < target) {left++;} else {right--;}}}return result;}

2. 滑動窗口經典題型最小覆蓋子串(LeetCode 76

算法核心思想

? 滑動窗口(Sliding Window)算法?是解決最小覆蓋子串問題的最優方法:

  1. ?雙指針定義窗口?:使用leftright兩個指針表示當前考察的子串窗口
  2. ?哈希表記錄需求?:使用兩個哈希表分別存儲:
  • need:目標字符串T中各字符的需求量
  • window:當前窗口中滿足需求的字符數量

? ? ? 3. 動態擴展收縮窗口?:

  • 先擴展right指針尋找可行解
  • 再收縮left指針優化解

? ? ? 4.?有效字符計數?:通過valid變量統計窗口中已滿足需求的字符種類數

? ? ? 5. 實時更新結果?:每當找到更小的滿足條件的子串時更新結果

復雜度分析

  • ?時間復雜度?:O(n),其中n是字符串S的長度
  • ?空間復雜度?:O(m),其中m是字符集大小(通常為常數級)

Java實現代碼

public String minWindow(String s, String t) {// 邊界條件檢查if (s == null || t == null || s.length() < t.length()) {return "";}// 初始化需求哈希表,記錄t中每個字符出現的次數Map<Character, Integer> need = new HashMap<>();for (char c : t.toCharArray()) {need.put(c, need.getOrDefault(c, 0) + 1);}// 初始化窗口哈希表,記錄當前窗口中滿足需求的字符數量Map<Character, Integer> window = new HashMap<>();// 記錄窗口中滿足need條件的字符個數int valid = 0;// 記錄最小覆蓋子串的起始位置和長度int start = 0, minLen = Integer.MAX_VALUE;// 滑動窗口左右指針int left = 0, right = 0;while (right < s.length()) {// 獲取右指針當前字符char c = s.charAt(right);// 右指針向右移動right++;// 如果當前字符在需求表中,則更新窗口計數if (need.containsKey(c)) {window.put(c, window.getOrDefault(c, 0) + 1);// 如果窗口中該字符數量等于需求數量,則valid加1if (window.get(c).equals(need.get(c))) {valid++;}}// 當窗口滿足所有字符需求時,嘗試收縮左邊界while (valid == need.size()) {// 更新最小覆蓋子串信息if (right - left < minLen) {start = left;minLen = right - left;}// 獲取左指針當前字符char d = s.charAt(left);// 左指針向右移動left++;// 如果移出的字符在需求表中,則更新窗口計數if (need.containsKey(d)) {// 如果窗口中該字符數量剛好等于需求數量,則valid減1if (window.get(d).equals(need.get(d))) {valid--;}window.put(d, window.get(d) - 1);}}}// 返回最小覆蓋子串,如果沒有找到則返回空字符串return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);}

、算法選擇的核心判別特征

1. 雙指針算法的識別特征

當問題呈現以下?至少兩個?特征時,優先考慮雙指針算法:

  • ?線性序列結構?(數組/鏈表)
    • 典型表現:輸入數據為數組或鏈表等線性結構
    • 反例:樹形結構或圖結構通常不適用
  • ?有序性或可排序性?
    • 典型表現:題目明確說明"已排序"或允許預處理排序
    • 示例特征:"非遞減順序排列"、"你可以假設數組已經按升序排列"
  • ?對稱性/雙向操作需求?
    • 典型表現:需要從兩端向中間或特定方向協同操作
    • 示例場景:回文判斷、盛水容器問題
  • ?組合優化問題?
    • 典型表現:需要尋找兩個或多個元素的特定組合
    • 示例模式:"找出滿足條件的兩個元素"、"確定三個數的組合"

2. 滑動窗口算法的識別特征

當問題呈現以下?至少兩個?特征時,優先考慮滑動窗口算法:

  • ?連續子區間要求?
    • 典型表現:需要處理數組中連續的序列或子串
    • 關鍵詞:"連續子數組"、"子串"、"連續的...滿足條件"
  • ?窗口可變或固定大小?
    • 典型表現:需要動態調整或保持固定大小的區間
    • 可變窗口特征:"最短/最長滿足條件的..."
    • 固定窗口特征:"大小為k的..."
  • ?統計類約束條件?
    • 典型表現:基于頻率、和、平均值等統計量的條件判斷
    • 示例條件:"包含所有字符"、"和≥target"、"無重復字符"
  • ?最優解搜索?
    • 典型表現:需要尋找滿足特定條件的最優區間
    • 典型目標:"最小的...滿足..."、"最大的...滿足..."

3. 特征驗證案例

案例1:三數之和(雙指針)

  • ? 線性結構(數組)
  • ? 可排序性(題目允許排序)
  • ? 組合問題(找三個數)
  • ? 對稱操作(需要跳過重復解)

案例2:最小覆蓋子串(滑動窗口)

  • ? 連續子區間(子串要求連續)
  • ? 可變窗口(找最短滿足條件的)
  • ? 統計條件(包含所有字符)
  • ? 最優解搜索(最小窗口)

4. 應用場景選擇指南

1. 優先選擇雙指針的情況
  • ?有序數組的組合問題?:如兩數之和、三數之和
  • ?鏈表操作?:如環形鏈表檢測、鏈表中點定位
  • ?對稱性問題?:如回文串驗證、反轉字符串?
2. 優先選擇滑動窗口的情況
  • ?連續子序列問題?:如最小覆蓋子串、最長無重復子串
  • ?區間統計問題?:如和大于等于目標值的最短子數組
  • ?固定窗口大小問題?:如大小為k的子數組的最大平均值?

、力扣經典案例

4.1、基礎雙指針問題

4.1.1. 對撞指針經典題
  • 167. 兩數之和 II - 輸入有序數組
    • 解法特點:有序數組相向指針遍歷
    • 時間復雜度:O(n)
  • 344. 反轉字符串
    • 解法特點:原地操作字符數組
    • 空間復雜度:O(1)

4.2、滑動窗口常規問題

4.2.1. 可變窗口基礎題
  • 209. 長度最小的子數組
    • 解法特點:動態調整窗口大小
    • 關鍵點:維護窗口和與目標值的比較
4.2.2. 哈希表輔助窗口題
  • 3. 無重復字符的最長子串
    • 解法特點:哈希表記錄字符最后出現位置
    • 時間復雜度:O(n)

4.3、字符串匹配問題

4.3.1. 困難級窗口問題
  • 76. 最小覆蓋子串
    • 解法特點:精確的窗口收縮條件
    • 關鍵點:有效字符計數機制
4.3.2. 固定窗口典型題
  • 438. 找到字符串中所有字母異位詞
    • 解法特點:固定長度窗口滑動
    • 優化點:數組替代哈希表統計字符

4.4、鏈表雙指針問題

4.4.1. 快慢指針經典題
  • 141. 環形鏈表
    • 解法特點:Floyd判圈算法
    • 空間復雜度:O(1)

4.4.2. 前后指針應用

  • 19. 刪除鏈表的倒數第 N 個結點
    • 解法特點:前后指針保持固定間距
    • 關鍵點:虛擬頭節點處理邊界

4.5、多維滑動窗口問題

4.5.1. 單調隊列配合題
  • 239. 滑動窗口最大值
    • 解法特點:單調遞減隊列維護窗口極值
    • 時間復雜度:O(n)
4.5.2. 雙堆進階問題
  • 480. 滑動窗口中位數
    • 解法特點:大小頂堆平衡維護中位數
    • 關鍵點:延遲刪除策略

結語:算法精進的階梯

掌握雙指針和滑動窗口不僅是面試的敲門磚,更是提升算法思維的關鍵。建議讀者按照解題模板→理解原理→獨立實現→優化變體的路徑系統學習,逐步構建自己的算法兵器庫。

附高頻核心算法

動態規劃(DP):從核心場景識別到優化技巧

堆排序:原理、實現與優化

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

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

相關文章

蘋果MAC、MacBook air和pro安裝windows雙系統與iOS分發

文章目錄1. main1.1 準備工作1.2 啟動轉換助理1.3 Windows安裝1.4 蘋果電腦安裝Windows雙系統切換2. 蘋果(iOS)分發/上架2.1 上架App Store2.2 上架TestFlight2.3 webClip免簽上架2.4 超級簽名2.5 企業證書2.6 app分發系統Reference1. main 蘋果電腦安裝windows雙系統 https:…

ArcGIS定向影像(1)——非傳統影像輕量級解決方案

常常聽到這樣的需求&#xff0c;ArcGIS能讓用戶自己低成本的做出谷歌街景嗎&#xff1f;現在 _ArcGIS Pro 3.2 和 ArcGIS Enterprise 11.2 _能夠讓用戶不使用任何插件和擴展的情況下完成街景數據集的構建&#xff0c;數據管理&#xff0c;發布服務和調用的完整解決方案。非常體…

uni-app 網絡之封裝實戰HTTP請求框架

前言在uniapp開發中&#xff0c;網絡請求是每個應用都必不可少的功能模塊。一個優秀的網絡請求封裝不僅能提高開發效率&#xff0c;還能增強代碼的可維護性和可擴展性。本文將基于實際項目經驗&#xff0c;詳細介紹如何封裝一個高效、可維護的Uniapp網絡請求框架&#xff0c;并…

架構師成長之路-架構方法論

文章目錄前言一、先搞懂&#xff1a;架構師不僅僅是“技術大佬”&#xff0c;更是“問題解決者”1.1 架構師的分類&#xff1a;不止“開發架構師”一種1.2 架構師要關注什么&#xff1f;別只盯著技術1.3 架構師解決問題的4步心法&#xff1a;從定義到落地1.4 架構師的成長攻略&…

uniapp在微信小程序中實現 SSE 流式響應

前言 最近需要使用uniapp開發一個智能對話頁面&#xff0c;其中就需要使用SSE進行通信。 本文介紹下在uniapp中如何基于uni.request實現SSE流式處理。 在線體驗 #小程序:yinuosnowball SSE傳輸格式 返回輸出的流式塊: Content-Type為text/event-stream 每個流式塊均為 d…

STM32N6AI資料匯總

文章目錄前言一、STM32N6硬件資源1.1 NUCLEO-N657X0-Q1.2 STM32N6570-DK1.3 正點原子STM32N647二、STM32N6軟件資源2.1 STM32CubeN6例程資源包2.2 STM32圖像信號處理器&#xff08;ISP&#xff09;調優軟件2.3 正點原子N6開發板配套軟件三、AI軟件資源3.1 STM32N6 AI軟件包總結…

Flask學習筆記(一)

1、環境準備pip install Flask使用Flask開發第1個入門程序&#xff1a;from flask import Flask app Flask(__name__) app.route(/) def hello_world():return Hello, World!if __name__ __main__:app.run()Flask構造函數將當前模塊的名稱(__name__)作為參數。2、route函數ap…

CSP認證練習題目推薦(4)

思維、貪心、綜合 排隊打水 這道題目不算難&#xff0c;但是不注意還是會出現很多錯誤&#xff0c;比如結構體的書寫。以及自定義結構體排序。還有這里做的優化&#xff0c;使用前綴和記錄打水的等待時間&#xff0c;但是這里很容易出錯的點在于等待時間是應該是記錄的前一個…

MySQL 視圖的更新與刪除:從操作規范到風險防控

MySQL 視圖的更新與刪除&#xff1a;從操作規范到風險防控 視圖作為 “虛擬表”&#xff0c;其更新與刪除操作常常讓開發者困惑 ——“為什么更新視圖會報錯&#xff1f;”“刪除視圖會不會弄丟數據&#xff1f;” 實際上&#xff0c;80% 的視圖操作問題都源于對 “視圖依賴基表…

C 語言實現 I.MX6ULL 點燈(續上一篇)、SDK、deep及bsp工程管理

目錄 一、匯編點燈轉 C 語言實現 1. 關鍵字&#xff1a;volatile 2. 寄存器地址定義&#xff08;兩種方式&#xff09; &#xff08;1&#xff09;直接宏定義地址 &#xff08;2&#xff09;結構體封裝寄存器&#xff08;優化訪問&#xff09; 3. 核心功能代碼 &#xff…

DevOps實戰(7) - 使用Arbess+GitPuk+sourcefare實現Node.js項目自動化部署

Arbess 是一款國產開源免費的 CI/CD 工具&#xff0c;工具支持一鍵部署&#xff0c;頁面簡潔易用。本文將詳細介紹如何安裝配置使用GitPuk、sourcefare、Arbess系統&#xff0c;使用流水線拉取GitPuk源碼、使用sourcefare代碼掃描、構建安裝包并進行主機部署。 1、GitPuk 安裝…

算法,蒜鳥蒜鳥-P1-理解“雙指針”

歡迎來到啾啾的博客&#x1f431;。 記錄學習點滴。分享工作思考和實用技巧&#xff0c;偶爾也分享一些雜談&#x1f4ac;。 有很多很多不足的地方&#xff0c;歡迎評論交流&#xff0c;感謝您的閱讀和評論&#x1f604;。 目錄引言1 雙指針&#xff1a;Two Pointers1.1 左右指…

使用cookiecutter創建python項目

一、關于Python項目結構Python 項目并沒有完全統一的 “固定結構”&#xff0c;但行業內有一些廣泛遵循的約定俗成的目錄結構&#xff08;尤其針對可分發的包或大型項目&#xff09;。同時&#xff0c;確實有工具可以快速生成這些標準化結構&#xff0c;提高開發效率&#xff0…

臺積電生態工程深度解析:從晶圓廠到蜂巢的系統架構遷移

當半導體巨頭將工廠視為生態系統&#xff0c;用工程思維解決環境問題概述&#xff1a;生態系統的工程化再造臺積電近日開展的"積蜜"項目絕非簡單的企業CSR行為&#xff0c;而是一場將生態系統視為復雜系統進行工程化改造的技術實踐。本文將從系統架構、數據監控、循環…

從零實現一個簡易計算器

最近在刷算法題時&#xff0c;遇到了實現計算器的問題。一開始覺得很簡單&#xff0c;但真正動手實現時才發現其中有很多細節需要考慮。今天就來分享一下我的實現思路和學到的經驗。問題分析我們需要實現一個能夠處理加減乘除四則運算的計算器&#xff0c;要正確處理運算符的優…

Actix-webRust Web框架入門教程

文章目錄引言Actix-web是什么&#xff1f;準備工作你的第一個Actix-web應用理解代碼結構處理請求和響應接收請求數據返回響應中間件 - 增強你的應用狀態管理和依賴注入實用示例&#xff1a;構建RESTful API測試你的Actix-web應用部署Actix-web應用結語額外資源引言 嘿&#xf…

若依框架前端通過 nginx docker 鏡像本地運行

1. 前言 項目運行過程圖&#xff1a;對于前端項目通過命令 npm run build 打包后&#xff0c;無法直接運行。存在如下錯誤&#xff1a;可以通過配置 nginx 服務器運行前端項目解決如上問題。 2. Nginx 運行 采用 docker 鏡像的方式運行&#xff0c;docker-compose.yml 文件內容…

淺聊一下HTTP協議

在日常上網瀏覽網頁、刷視頻時&#xff0c;背后都離不開 HTTP 協議的支持。作為 Web 世界的 “交通規則”&#xff0c;它負責服務器和客戶端瀏覽器之間的數據傳輸。這篇文章就帶大家全面了解 HTTP 協議&#xff0c;從基本概念到通信細節&#xff0c;再到安全相關的 HTTPS&#…

機器人控制器開發(定位——cartographer ros2 使用2)

文章總覽 1 純定位模式 當完成建圖后&#xff0c;會生成pbstream格式的地圖文件 配置純定位模式的lua腳本 backpack_2d_localization.lua include "backpack_2d.lua"TRAJECTORY_BUILDER.pure_localization_trimmer {max_submaps_to_keep 3, } POSE_GRAPH.optimi…

《大數據之路1》筆記3:數據管理

一 元數據 1.1 元數據概述 定義&#xff1a; 元數據是關于數據的數據&#xff0c;元數據打通了源數據、數據倉庫、數據應用&#xff0c;記錄了數據從生產到消費的全部過程。元數據主要記錄數據倉庫中模型的定義、各層級間的映射關系、監控數據倉庫的數據狀態和ETL的任務運行狀態…