easy 級例題:給定乙個遞增的具有n個元素的正整數序列arr和乙個正整數s,求序列中兩個不同位置的數a和b,使他們的和恰好等於s,輸出所有滿足條件的結果i和j。如序列arr = 和正整數s = 9, 就有 4 + 5 和 3 + 6 。
本例最簡單的方法就是利用二重迴圈列舉所有的可能性,得出結果。但是這樣做的時間複雜度為o(n^2),顯然是低效率的。
這裡利用序列本身的特性和雙指標two pointers的思想來解決這個問題。
對於乙個確定的arr[i], 如果某個的arr[j]滿足arr[i] + arr[j] == s
時,有arr[i] + arr[j + 1] > s
,則不需要對j以後的情況進行列舉。
對於某個arr[i], 可以找到乙個確定的arr[j]當arr[i] + arr[j] == s
時,有arr[i+1] + arr[j] > s
,則不需要對i以後的情況進行列舉。
那麼對於這個問題可以採用two pointers的思想。先讓i = 0, j = n - 1,也就是i指標指向第乙個元素,j指標指向最後乙個元素。根據arr[i] + arr[j]和s的大小來決定i向右移還是j向左移,直到i >= j。
判斷條件如下:
1)如果arr[i] + arr[j] == s
,則輸出結果。且由於序列遞增,可以知道arr[i+1] + arr[j] > s
,arr[i] + arr[j-1] < s
,arr[i+1] + arr[j-1]
和s的大小關係不確定,所以等於s的結果只能是在[i+1, j-1]之間。
2)如果arr[i] + arr[j] < s
,則有arr[i] + arr[j-1] < s
,但是arr[i+1] + arr[j]
和s的大小關係不確定,則i向右移,i++。
3)如果arr[i] + arr[j] > s
,則有arr[i+1] + arr[j] > s
,但是arr[i] + arr[j-1]
和s的大小關係不確定,則j向左移,j–。
**如下:
while
(i < j)
else
if(arr[i]
+ arr[j]
< s)
else
}
easy+ 級例題:序列合併問題,將兩個遞增序列arr_1和arr_2合併為乙個遞增序列arr_3;
將i設定為arr_1序列的首元素,j設定為arr_2序列的首元素,然後通過比較大小來看那個該放入序列arr_3。
1)如果arr_1[i] > arr_2[j]
,說明現在arr_2[j]
是當前最小的乙個,放入arr_3中,然後j++。
2)如果arr_1[i] < arr_2[j]
,說明現在arr_1[i]
是當前最小的乙個,放入arr_3中,然後i++。
1)如果arr_1[i] == arr_2[j]
,則任選乙個放入arr_3,然後把對應的pointer++。
//l1為陣列arr_1的元素個數,l2為陣列arr_2的元素個數
intmergearray
(const
int arr_1,
const
int arr_2,
int arr_3,
int l1,
int l2)
else
}//將剩餘的全部加入到陣列arr_3中
while
(i < l1) arr_3[index++
]= arr_1[i++];
while
(j < l2) arr_3[index++
]= arr_2[j++];
return index;
//返回arr_3陣列元素個數
}
演算法筆記 two pointers
從乙個題目引入 給定乙個序列和正整數m 8,求序列中的兩個數 a b m本題最直接的解法就是列舉 for int i 0 i n i 顯然,這個解法的時間複雜度為o n 當n為 10 5 的規模是不可承受的 利用序列的遞增特性,我們可以利用以下解法 反覆執行直到i j成立 while i j els...
Two pointers技巧的應用
查詢陣列中兩個位置不同的數字之和為sum的個數。先來看看暴力法,粗略估計,時間複雜度為0 n 2 void violence int a,int totalnumber,int sum int count 0 計算不匹配的結果次數 不匹配次數是41次,嗯,看起來結果還不錯的樣子。來看看two poi...
關於Two pointers的個人理解
剛剛在刷題的時候接觸到了一道題,題的大意是給出乙個遞增的數字序列,並給出乙個m,要求找到a,b兩個數字,且和為m,並且atwo pointers思想是對有序陣列的優化遍歷 如果根據題目中的思想,進行兩層列舉,則不可避免地會使時間複雜度到達o n 2 級別。但是可以針對序列遞增這一條進行優化 對這個有...