【數據結構與算法Trip第3站】雙指針

我們來詳細講解一下算法中非常常用且重要的技巧——雙指針法。

這是一個概念清晰但應用極其廣泛的技術,掌握它能幫助你高效解決許多問題。

一、什么是雙指針法?

核心思想:顧名思義,就是在遍歷對象(通常是數組或鏈表)時,使用兩個相同方向或相反方向的指針(索引)進行掃描,通過指針的移動和相互配合來解決問題,從而避免不必要的循環,將暴力解法的時間復雜度優化到 O(n) 級別。

為什么有效? 它通過巧妙地利用問題的內在邏輯(如有序性),避免了大量的重復計算,將復雜度從 O(n2) 降低到 O(n)。

二、雙指針的三種常見類型

雙指針法主要有三種常見的應用形式,我們結合例子來理解。

1. 快慢指針(前后指針)

兩個指針從同一側開始遍歷,但移動速度不同(例如,一個一次走一步,一個一次走兩步)。常用于鏈表問題。

典型問題:判斷鏈表是否有環
? 思路:設置兩個指針 slow 和 fast,起始位置都在鏈表頭。

?   slow 每次向后移動一個節點。?   fast 每次向后移動兩個節點。

? 判斷:

?   如果鏈表中沒有環,fast 指針會先到達鏈表尾部(遇到 null)。?   如果鏈表中有環,fast 指針最終會追上 slow 指針(fast == slow),就像在環形跑道上賽跑一樣。

? 代碼示例 (Python)
class ListNode:
def init(self, x):
self.val = x
self.next = None

def hasCycle(head: ListNode) -> bool:if not head or not head.next:return Falseslow = headfast = head.nextwhile slow != fast:# 如果fast或fast.next為空,說明到了鏈表末尾,無環if not fast or not fast.next:return Falseslow = slow.nextfast = fast.next.next # fast每次走兩步# 如果slow等于fast,說明有環return True

? 其他應用:尋找鏈表的中間節點、尋找鏈表的倒數第 k 個節點。

2. 左右指針(對撞指針)

兩個指針分別從序列的兩端向中間移動,直到它們相遇。前提通常是序列是有序的。

典型問題:兩數之和 II - 輸入有序數組 (LeetCode 167)
題目:給定一個已按升序排列的整數數組 numbers,請你從數組中找出兩個數滿足相加之和等于目標數 target。假設每個輸入只對應唯一的答案,且不可以重復使用相同的元素。

? 暴力法:兩層循環,時間復雜度 O(n2)。

? 雙指針法:利用有序這個關鍵特性。

?   步驟:1.  初始化:左指針 left = 0,右指針 right = len(numbers) - 1。2.  循環條件:while left < right。3.  計算 sum_val = numbers[left] + numbers[right]。4.  判斷:?   如果 sum_val == target,找到答案,返回 [left+1, right+1] (題目要求索引從1開始)。?   如果 sum_val < target,說明總和太小,需要增大。因為數組有序,所以將 left 右移(left += 1)。?   如果 sum_val > target,說明總和太大,需要減小。將 right 左移(right -= 1)。

? 代碼示例 (Python)
def twoSum(numbers: List[int], target: int) -> List[int]:
left, right = 0, len(numbers) - 1

    while left < right:s = numbers[left] + numbers[right]if s == target:return [left + 1, right + 1]elif s < target:left += 1else:right -= 1return [-1, -1] # 題目保證有解,這行不會執行

? 為什么正確? 每次移動都排除了大量不可能的解,縮小了搜索范圍。

? 其他應用:二分查找、反轉字符串、三數之和、盛最多水的容器。

3. 滑動窗口(也是雙指針的一種)

兩個指針形成一個窗口(區間),通過移動指針的起始位置來動態地擴展或收縮這個窗口。常用于子串、子數組問題。

典型問題:長度最小的子數組 (LeetCode 209)
題目:給定一個含有 n 個正整數的數組和一個正整數 target。找出該數組中滿足其和 ≥ target 的長度最小的連續子數組,并返回其長度。

? 思路:

?   使用兩個指針 left 和 right,代表窗口的左右邊界。?   right 指針向右移動,擴大窗口,直到窗口內的元素總和 >= target。?   一旦滿足條件,記錄當前窗口長度,然后 left 指針向右移動,收縮窗口,嘗試尋找更小的窗口,同時更新窗口和。?   重復上述過程,直到 right 到達數組末尾。

? 代碼示例 (Python)
def minSubArrayLen(target: int, nums: List[int]) -> int:
left = 0
total = 0
min_len = float(‘inf’) # 初始化為一個極大值

    # right指針遍歷整個數組,作為窗口的右邊界for right in range(len(nums)):total += nums[right] # 擴大窗口,加入right指向的元素# 當窗口總和滿足條件時,收縮左邊界while total >= target:# 更新最小長度current_len = right - left + 1min_len = min(min_len, current_len)# 縮小窗口,從總和里減去left指向的元素,并移動lefttotal -= nums[left]left += 1return 0 if min_len == float('inf') else min_len

? 其他應用:字符串的排列、找到字符串中所有字母異位詞、最小覆蓋子串。

三、總結與要點

類型 指針方向 典型應用 關鍵特點

快慢指針 同向,速度不同 鏈表判環,找中點 常用于鏈表數據結構

左右指針 相向而行 有序數組的兩數之和,反轉數組 序列有序是關鍵前提

滑動窗口 同向,一前一后 最小長度子數組,字符串匹配 維護一個動態變化的區間

使用雙指針法的核心要點:

  1. 分析問題特性:先思考暴力解法,再看數據是否有有序、單調性等特性,能否用指針移動來避免重復計算。
  2. 確定指針含義:明確每個指針代表什么(如鏈表的節點、數組的索引)。
  3. 確定移動規則:想清楚在什么條件下移動哪個指針,以及移動多少。
  4. 注意邊界條件:仔細處理指針越界、相遇、初始位置等情況。

希望這個詳細的講解能幫助你徹底理解雙指針法!多加練習是掌握它的最好方式。

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

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

相關文章

時序數據庫選型指南:基于大數據視角的IoTDB應用優勢分析詳解!

目錄 一、時序數據庫選型的基本原則 1.1 數據特征與需求分析 1.1.1 數據規模與寫入負載 1.1.2 查詢需求 1.1.3 數據保留與歸檔策略 1.1.4 系統擴展性與高可用性 1.2 技術架構與系統性能評估 1.2.1 寫入性能 1.2.2 查詢性能 1.2.3 數據壓縮能力 1.2.4 高可用性與災備…

緩存三大劫攻防戰:穿透、擊穿、雪崩的Java實戰防御體系(三)

第三部分&#xff1a;緩存雪崩——大量key失效引發的“系統性崩潰” 緩存雪崩的本質是“大量緩存key在同一時間失效&#xff0c;或緩存集群整體故障”&#xff0c;導致請求全量穿透至DB&#xff0c;引發“系統性崩潰”。 案例4&#xff1a;電商首頁的“批量過期”災難 故障現場…

解決docker配置了鏡像源但還會拉取官方鏡像源的問題

&#x1f3d3;我們有時候雖然配置了Docker國內鏡像源&#xff0c;但是還是會繞過去請求官方鏡像源&#xff08;docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded&#xff09;&#xff0c;現在我們就來解決一…

R語言水文、水環境模型優化:從最速上升法、嶺分析到貝葉斯優化與異方差處理,涵蓋采樣設計、代理模型與快速率定等

在水利工程、環境治理、生態保護、機械設計與航天航空等現代工業與科學領域&#xff0c;數學模型已成為不可或缺的核心分析、預測與決策工具。然而&#xff0c;隨著系統復雜性的日益增長&#xff0c;模型構建的精確性、參數率定的效率以及不確定性量化的重要性被提到了前所未有…

關于數據采集與處理心得(一)

目前所實踐的經驗告知我&#xff01;1. 別企圖妄想一個腳本解決所有問題要學會對問題分解&#xff0c;編寫多個腳本一步步將問題解決&#xff0c;如果每一個步驟都為了下一個階段的成果打地基&#xff0c;也是非常OK的。同時要盡可能將每一個編寫的腳本都盡到最大的利用率2. 編…

IvorySQL 適配 LoongArch? 龍架構

IvorySQL 社區很高興向您宣布&#xff0c;IvorySQL 已成功適配LoongArch 龍架構&#xff0c;為國產數據庫與國產芯片的深度融合邁出了堅實一步。這一里程碑標志著 IvorySQL 在推動國產化生態建設、賦能信創產業方面取得了重大突破&#xff0c;為用戶提供更高效、穩定、安全的數…

數據庫分庫分表是考慮ShardingSphere 還是Mycat?

http://www.mycat.org.cn/ https://shardingsphere.apache.org/ 這是一個非常核心且優秀的問題。在選擇 ShardingSphere 和 Mycat 之間&#xff0c;對于游戲這種高性能、高復雜度的場景&#xff0c;目前行業內的主流選擇和發展趨勢毫無疑問是 ShardingSphere。 我會為你詳細對…

mysql分庫分表數據量核查問題

場景&#xff1a; 使用分庫分表的業務有時分庫數量幾百甚至上千&#xff0c;當主管需要查詢每個庫中的數據&#xff0c;掌握數據分布情況。要你查看哪些庫中的表數量大于某個量級的給找出來 &#xff0c;你會怎么做。 例子 &#xff1a; mysql庫數量&#xff1a;db_xx_devicein…

python之socket網絡編程

引言 在互聯網時代&#xff0c;網絡編程已經成為開發人員必備的技能之一。無論是Web開發、實時通信還是分布式計算&#xff0c;都離不開網絡編程的支持。Python提供的socket模塊為我們提供了簡潔而強大的接口&#xff0c;可以輕松實現客戶端和服務器之間的通信。 Socket編程是網…

WPF Telerik.Windows.Controls.Data.PropertyGrid 自定義屬性編輯器

1.AI幫忙定義新用戶控件 2.在屬性上添加TelerikEditorAttribute特性 private ObservableCollection<string> _axisOrder;[Display(Description "點位", GroupName "通用", Name "軸&順序", Order 1)][DataMember][TelerikEditorAt…

【超詳細】別再看零散的教程了!一篇搞定Gitee從注冊、配置到代碼上傳與管理(內含避坑指南最佳實踐)

&#x1f525;個人主頁&#xff1a;艾莉絲努力練劍 ?專欄傳送門&#xff1a;《C語言》、《數據結構與算法》、C語言刷題12天IO強訓、LeetCode代碼強化刷題、洛谷刷題、C/C基礎知識知識強化補充、C/C干貨分享&學習過程記錄 &#x1f349;學習方向&#xff1a;C/C方向學習者…

43.shell腳本循環與函數

shell腳本循環與函數 for 循環 for 循環用于一次性讀取多個信息&#xff0c;逐一對信息進行操作處理&#xff0c;特別適合處理有范圍的數據 語法 for 變量名 in 取值列表 do命令序列 done批量創建用戶 #!/bin/bashtouch /root/users.txt echo aka blues cloe dio foks > /ro…

模型部署:(四)安卓端部署Yolov8-v8.2.99實例分割項目全流程記錄

模型部署&#xff1a;&#xff08;四&#xff09;安卓端部署Yolov8-v8.2.99實例分割項目全流程記錄1、下載ncnn2、下載opencv-mobile3、文件拷貝4、andorid_studio相關配置5、文件內參數設置5、重構項目&#xff1a;6、打包apk7、部署自己訓練的實例分割模型1、下載ncnn 地址&…

高并發、低延遲全球直播系統架構

一、 核心架構圖 整個系統的數據流和工作流程如下圖所示&#xff0c;它清晰地展示了從主播推流到觀眾觀看的完整過程&#xff1a; #mermaid-svg-QzNpj0DWxd5FERPC {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QzN…

AWS strands agents 當智能體作為獨立服務/容器部署時,它們無法共享進程內狀態

當智能體作為獨立服務/容器部署時&#xff0c;它們無法共享進程內狀態。 以下是針對分布式部署中動態內存庫的生產就緒解決方案&#xff1a;1. 基于外部存儲的內存庫基于 DynamoDB 的共享內存import boto3 from strands import Agent, tool from typing import Dict, Any impor…

第五節 JavaScript——引用類型、DOM/BOM 與異步編程

JavaScript 的第五節課通常會深入探討 ??引用類型、DOM 操作、BOM 操作、事件處理以及異步編程?? 等核心概念。這些知識能讓你創建動態交互豐富的網頁。下面我將詳細講解這些內容并提供示例。 ?? JavaScript 第五節:引用類型、DOM/BOM 與異步編程 ? 一、引用類型 引…

使用Pycharm進行遠程ssh(以Featurize為例)

使用Pycharm進行遠程ssh&#xff08;以Featurize為例&#xff09;文章目錄介紹應用背景遠程連接Python連接Jupyter介紹應用背景 在使用Pycharm 專業版的時候進行遠程ssh連接服務器&#xff08;Featurize&#xff09;的Python解釋器和Jupyter 遠程連接Python 打開Pycharm點擊…

深入研究:ClickHouse中arrayExists與hasAny在ORDER BY場景下的性能差異

最近公司大數據情況下ClickHouse查詢性能極差&#xff0c;后來發現在大數據量ORDER BY場景下&#xff0c;arrayExists(x -> x in ...)比hasAny性能快10倍&#xff01;&#xff01;&#xff01;&#xff01; 一、問題重述與研究背景 在大數據量 ORDER BY場景下&#xff0c;…

Spring AI (二)結合Mysql做聊天信息存儲

上文講了&#xff0c;用Spring ai做簡單的聊天功能&#xff0c;沒看過的可以查看下 Spring AI結合豆包模型 這里簡單結合下Jdbc做下聊天記錄的存儲和查詢&#xff0c;讓對話變的更智能。 首先是Pom的支持 <dependency><groupId>org.springframework.ai</grou…

【docker】data-root 數據遷移(防止無法加載鏡像和容器問題)

操作系統&#xff1a;ubuntu 24.04 docker版本&#xff1a;docker-ce 28.1.1 目標&#xff1a;將/var/lib/docker 的數據遷移到/data/docker停止docker sudo systemctl stop docker.socket sudo systemctl stop docker這個步驟一定要做&#xff0c;否則容易導致數據不一致。 rs…