演算法核心思想:
雙指標多用於遍歷陣列,可以同時遍歷乙個陣列或分別遍歷不同的陣列。常見的設計思想如下:
對於排序後的陣列,雙指標分別指向陣列的頭尾,遍歷方向相反,用於搜尋。
雙指標指向兩個陣列,分別遍歷
快慢指標
滑動視窗
兩數之和
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...