資料結構演算法 雙指標

2021-10-22 18:47:27 字數 4101 閱讀 5117

演算法核心思想:

雙指標多用於遍歷陣列,可以同時遍歷乙個陣列或分別遍歷不同的陣列。常見的設計思想如下:

對於排序後的陣列,雙指標分別指向陣列的頭尾,遍歷方向相反,用於搜尋。

雙指標指向兩個陣列,分別遍歷

快慢指標

滑動視窗

兩數之和

167. two sum ii - input array is sorted (easy)

題目描述

在乙個增序的整數陣列裡找到兩個數,使它們的和為給定值。已知有且只有一對解。

輸入輸出樣例

輸入是乙個陣列(numbers)和乙個給定值(target)。輸出是兩個數的位置,從 1 開始計數。

input: numbers = [2,7,11,15], target = 9

output: [1,2]

在這個樣例中,第乙個數字(2)和第二個數字(7)的和等於給定值(9)。

核心思路:兩個指標分別指向陣列的頭尾,相向而行遍歷,若判斷結果大於則增加左指標,若小於則減小右指標

class

solution;}

if((*p_front +

*p_behind)

< target)if(

(*p_front +

*p_behind)

> target)}}

};intmain()

; solution s;

vector<

int> ret;

ret= s.

twosum

(numbers,8)

; cout << ret[0]

<<

" "<< ret[1]

<< endl;

}

歸併兩個有序陣列

merge sorted array (easy)

題目描述

給定兩個有序陣列,把兩個陣列合併為乙個。

輸入輸出樣例

輸入是兩個陣列和它們分別的長度 m 和 n。其中第乙個陣列的長度被延長至 m + n,多出的

n 位被 0 填補。題目要求把第二個陣列歸併到第乙個陣列上,不需要開闢額外空間。

input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3

output: nums1 = [1,2,2,3,5,6]

核心思想:兩個指標分別遍歷兩個陣列進行比較,每次將較大的放到第乙個陣列的末尾,並自減,第三個指標用來管理複製,如果第二個陣列先複製完了,則剩下的陣列不需要改變,若第乙個陣列先複製完,則將第二個陣列剩餘的元素放到第乙個陣列的頭部

#include

#include

#include

#include

using namespace std;

class solution

while

(n >=0)

}};int

main()

; vector<

int> nums2

; solution s;

s.merge

(nums1,

3, nums2,nums2.

size()

);for(

int i =

0; i < nums1.

size()

; i++

)}

快慢指標

142. linked list cycle ii (medium)

題目描述

給定乙個鍊錶,如果有環路,找出環路的開始點。

輸入輸出樣例

輸入是乙個鍊錶,輸出是鍊錶的乙個節點。如果沒有環路,返回乙個空指標。

在這個樣例中,值為 2 的節點即為環路的開始點。

如果沒有特殊說明, leetcode 採用如下的資料結構表示鍊錶。

struct listnode

};核心思想:如果兩個人同時出發,如果賽道有環,那麼快的一方總能追上慢的一方。進一步想,追上時快的一方肯定比慢的一方多跑了幾圈,即多跑的路的長度是圈的長度的倍數。

原理:設起點到環的起點距離為m,已經確定有環,環的周長為n,(第一次)相遇點距離環的起點的距離是k。那麼當兩者相遇時,慢指標移動的總距離為i,i = m + a * n + k,因為快指標移動速度為慢指標的兩倍,那麼快指標的移動距離為2i,2i = m + b * n + k。其中,a和b分別為慢指標和快指標在第一次相遇時轉過的圈數。我們讓兩者相減(快減慢),那麼有i = (b - a) * n。即i是圈長度的倍數。利用這個結論我們就可以理解floyd解法為什麼能確定環的起點。將乙個指標移到鍊錶起點,另乙個指標不變,即距離鍊錶起點為i處,兩者同時移動,每次移動一步。當第乙個指標前進了m,即到達環起點時,另乙個指標距離鍊錶起點為i + m。考慮到i為圈長度的倍數,可以理解為指標從鍊錶起點出發,走到環起點,然後繞環轉了幾圈,所以第二個指標也必然在環的起點。即兩者相遇點就是環的起點。

/**

* definition for singly-linked list.

* struct listnode

* };

*/class solution

while

(fast != slow)

;

fast=head;

while

(fast!=slow)

return fast;}}

;

滑動視窗

76. minimum window substring (hard)

題目描述

給定兩個字串 s 和 t,求 s 中包含 t 所有字元的最短連續子字串的長度,同時要求時間

複雜度不得超過 o„n」。

輸入輸出樣例

輸入是兩個字串 s 和 t,輸出是乙個 s 字串的子串。

input: s = 「adobecodebanc」, t = 「abc」

output: 「banc」

在這個樣例中, s 中同時包含乙個 a、乙個 b、乙個 c 的最短子字串是「banc」。

核心思想:維護乙個動態變化的滑動視窗,尋找包含字串t中所有元素的最小解。

滑動規則:1.使右邊界增大,直到包含所有的t中所有的元素。2.縮小左邊界,直到不夠包含所有元素。此時為區域性最優解。

3.讓左邊界加1,使其不滿足條件,然後右邊界繼續增加直到又再次滿足條件。4.重複123步,直到右邊界越界。

這個題有點難寫,先放乙個別人的題解

class

solution

// 2: 開滑!

int left =

0, right =

0, n = s.

size()

, m = t.

size()

, cnt =0;

// 滑動視窗基本變數

int min_left =

0, min_size = int_max;

// 返回string的要求變數

while

(right < n)

if(flags[s[left]]&&

++chars[s[left]

]>0)

// 儲存標記發揮作用的時候

--cnt;

left++;}

}return min_size > n ?

"": s.

substr

(min_left, min_size);}

};intmain()

; string t =

; string out;

solution output;

out = output.

minwindow

(s, t)

;for

(const

auto

& p : out)

}

資料結構中雙指標的使用

我們在學習資料結構中的線性表,或者棧佇列的時候都遇到了初始化需要傳雙指標,初學者很不好理解為什麼要傳遞雙指標。我根據我個人學習的經驗寫了這個文章,希望對初學者有一些幫助。同時有不對的地方希望大神們補充。我們先簡單介紹函式呼叫時的三種引數傳遞的方法吧 1.簡單的值傳遞 這是函式引數傳遞中最簡單的一種,...

資料結構(鍊錶雙指標)2020 08 10

給定兩個 單向 鍊錶,判定它們是否相交並返回交點。請注意相交的定義基於節點的引用,而不是基於節點的值。換句話說,如果乙個鍊錶的第k個節點與另乙個鍊錶的第j個節點是同一節點 引用完全相同 則這兩個鍊錶相交。輸入 intersectval 8,lista 4,1,8,4,5 listb 5,0,1,8,...

資料結構與演算法 雙指標思想 首尾雙向遍歷

leetcode 兩數之和 ii 輸入有序陣列 題目描述 給定乙個已按照公升序排列 的有序陣列,找到兩個數使得它們相加之和等於目標數。函式應該返回這兩個下標值 index1 和 index2,其中 index1 必須小於 index2。示例 輸入 numbers 2,7,11,15 target 9...