日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法模板-双指针

發布時間:2024/4/11 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法模板-双指针 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介

在很多數組問題中,雙指針是一個反復被提及的解法。所謂雙指針,指的是在對象遍歷的過程中,并非單個指針進行訪問,而是使用兩個同向(快慢指針)或者反向(對撞指針)來進行掃描,從而達到相應的目的。也有時候,為了處理多數組問題使用多個指針,稱為分離指針。雙指針利用了數組是順序存儲這一特性,在某些情況下可以簡化運算并表現得很優雅。

快慢指針

快慢指針指的是兩個指針從數組同一側開始向另一側遍歷(即同向),將這兩個指針分別定義為快指針(fast)慢指針(slow),兩個指針以不同的策略移動,直到兩個指針的位置重合(或者其他終止條件),比較典型的例子是快指針每次移動兩步,慢指針每次移動一步。

快慢指針的經典例題為環形鏈表,題目和示例如下。

給定一個鏈表,判斷鏈表中是否有環。如果鏈表中存在環,則返回 true 。 否則,返回 false 。

示例

輸入:head = [3,2,0,-4], pos = 1 輸出:true 解釋:鏈表中有一個環,其尾部連接到第二個節點。

這道題雙指針的思路來源于Floyd 判圈算法(也叫龜兔賽跑算法),簡述如下。

若是兩個人從同一地點起跑,一個運動員速度快一個速度慢。那么當跑道有環的時候,跑得快的一定會比跑得慢的先進入環內并在環內移動,等到跑的慢的進入環里面的時候,由于跑的快的那個人速度快,他一定會在某個時刻與跑的慢的相遇,即套了跑的慢的若干圈。若跑道沒有環,顯然兩人永遠不會相遇。

借用上面的思路,我們可以定義一快一慢兩個指針,慢指針每次移動一步,快指針每次移動兩步。一開始這兩個指針都指向head,如果移動過程中快指針反過來追上了慢指針,那么一定存在環形鏈表,否則快的指針會到達鏈表尾部(鏈表無環)。

上述解法的Python代碼如下。

# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = Noneclass Solution:def hasCycle(self, head: ListNode) -> bool:p1, p2 = head, headwhile p2 != None and p2.next != None:p1 = p1.nextp2 = p2.next.nextif p1 == p2:return Truereturn False

對撞指針

對撞指針指的是兩個指針從數組的不同側向另一側移動(即反向),其中左側的稱為左指針(left),右側的稱為右指針(right)。需要注意的是,對撞指針適用于有序數組,當你遇到題意為有序數組時應當首先考慮對撞指針。

對撞指針的經典例題為兩數之和 II - 輸入有序數組,題目和示例如下。

給定一個已按照 非遞減順序排列 的整數數組 numbers ,請你從數組中找出兩個數滿足相加之和等于目標數target 。函數應該以長度為 2 的整數數組的形式返回這兩個數的下標值。numbers 的下標 從 1 開始計數 ,所以答案數組應當滿足 1 <= answer[0] < answer[1] <= numbers.length。你可以假設每個輸入 只對應唯一的答案 ,而且你 不可以 重復使用相同的元素。

示例

輸入:numbers = [2,7,11,15], target = 9 輸出:[1,2] 解釋:2 與 7 之和等于目標數 9 。因此 index1 = 1, index2 = 2 。

初始時兩個指針分別指向第一個元素位置和最后一個元素的位置。每次計算兩個指針指向的兩個元素之和,并和目標值比較。如果兩個元素之和等于目標值,則發現了唯一解。如果兩個元素之和小于目標值,則將左側指針右移一位。如果兩個元素之和大于目標值,則將右側指針左移一位。移動指針之后,重復上述操作,直到找到答案。由于題目說明答案唯一,因此一定可以找到唯一解。

上述解法的Python代碼如下。

class Solution:def twoSum(self, numbers: List[int], target: int) -> List[int]:left = 0right = len(numbers) - 1while left < right:if numbers[left] + numbers[right] < target:left += 1elif numbers[left] + numbers[right] > target:right -= 1else:return [left+1, right+1]

分離指針

分離指針在兩個不同的數組中,使用兩個不同的指針來進行遍歷。分離指針適用于雙數組或者多數組問題。

分離指針的經典例題為兩個數組的交集,題目和示例如下。

給定兩個數組,編寫一個函數來計算它們的交集。

示例

輸入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 輸出:[9,4]

這道題的雙指針解法為將兩個數組排序,然后兩個指針遍歷兩個數組。具體來看,兩個指針分別指向兩個數組的頭部,每次比較兩個指針指向位置的數字。若不等,則較小數字位置的指針右移;若相等且該數字不等于上次加入交集的值pre,則將該數字添加到交集中并更新pre,兩個指針都右移。當其中一個指針到達數組末端,停止遍歷。

上述解法的代碼如下。

class Solution:def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:nums1, nums2 = sorted(nums1), sorted(nums2)m, n = len(nums1), len(nums2)intersection = []i, j = 0, 0while i < m and j < n:num1, num2 = nums1[i], nums2[j]if num1 == num2:if not intersection or num1 != intersection[-1]:intersection.append(num1)i += 1j += 1elif num1 < num2:i += 1else:j += 1return intersection

練習題

對雙指針感興趣的可以訪問力扣上的雙指針專題,上一節以141題和167題為例簡單理解了快慢指針和對撞指針。

  • 快慢指針的題還有26. 刪除有序數組中的重復項、27. 移除元素、283. 移動零等。

  • 對撞指針的題還有15. 三數之和、16. 最接近的三數之和、881. 救生艇等。

  • 分離指針的題還有88. 合并兩個有序數組、350. 兩個數組的交集 II等。

補充說明

遇到數組的問題,應當首先想到使用雙指針進行解題,因為兩個指針的同時遍歷策略會大大減少時間和空間復雜度。

總結

以上是生活随笔為你收集整理的算法模板-双指针的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。