演算法筆記 two pointers

2022-02-19 09:29:16 字數 4291 閱讀 6816

從乙個題目引入:

給定乙個序列和正整數m = 8, 求序列中的兩個數 a + b = m
本題最直接的解法就是列舉:

for(int i = 0; i < n; i++)}}

顯然,這個解法的時間複雜度為o(n),當n為\(10^5\)的規模是不可承受的

利用序列的遞增特性,我們可以利用以下解法:

反覆執行直到i>=j成立

while(i < j)else if(a[i] + a[j] < m)else

}

這便是two pointers思想,充分利用了序列遞增的性質,使複雜度降低到o(n)

假設有兩個遞增序列a和b,要求將他們合併為遞增序列c
解法:

直到ij中的乙個到達序列末端為止,然後將另乙個序列的所有元素依次加入c中

int mergeabtoc(int a, int b, int c, int n, int m)else

}while(i < n) c[index++] = a[i++];

while(j < m) c[index++] = b[j++];

return index;

}

主要學習二路歸併排序,其原理為:將序列歸併為\([n/2]\)個組,組內單獨排序;然後將這些組再兩兩歸併排序,生成\([n/4]\)個組,組內再單獨排序;以此類推,直到剩下乙個組為止。歸併排序的時間複雜度為o(nlogn)

利用歸併排序實現
用乙個**來理解:只需要反覆將當前區間[left, right]分為兩半,對兩個子區間[left, mid][mid+1, right]分別遞迴進行歸併排序,然後將兩個已經有序的子區間合併為有序序列即可。

/*先實現將兩個陣列合併*/

int maxn = 100;

void merge(int a, int l1, int r1, int l2, int r2)else

}while(i <= r1) temp[index++] = a[i++];

while(j <= r2) temp[index++] = a[j++];

for(int i = 0; i < index; i++)

}

/*將array陣列當前區間[left, right]進行歸併排序*/

void mergesort(int a, int left, int right)

}

void mergesort(int a)}}

}

如果題目中只要求給出歸併排序每一趟結束的序列,那麼可以使用sort函式代替merge

void mergesort(int a)}}

快速排序的平均時間複雜度為o(logn),其要解決是:

對於序列a為,調整序列中元素的位置,使得a的左側所有元素不超過a, 右側所有元素都大於a, 如下圖:
解決該題最快的做法就是two pointers思想

舉例:

進行一次左右劃分:

// 對區間[left, right]進行劃分

int partition(int a, int left, int right)

a[left] = temp;

return left;

}

正式實現快速排序演算法

void quicksort(int a, int left, int right)

}

當序列中元素接近有序時,會達到最壞時間複雜度\(o(n^2)\),產生原因在於主元沒有把當前區間劃分為兩個長度接近的子區間。為了解決這一問題,我們要在序列中隨機選擇乙個主元,雖然最壞的情況下時間複雜度仍可能\(o(n^2)\),但是對於任意輸入資料的期望時間複雜度都能到達\(o(nlogn)\)

#include#include// 引數隨機數需要這兩個標頭檔案

#includeint main()

return 0;

}

rand()函式只能產生[0, rand_max]範圍內的整數(rand_maxstdlib.h中的乙個常數,不同系統中不同,如可能為:32767),所以想要產生[a,b]內的隨機數,應該使用rand() % (b - a + 1) + a

rand % (b - a + 1) + 0; // 產生範圍[0, b - a]

rand % (b - a + 1) + a; // 產生範圍[a, b]

#include#include#includeint main()

for(int i = 0; i < 10; i++)

}

如果要產生大於rand_max的隨機數時,可以如下:

演算法思維 two pointers

easy 級例題 給定乙個遞增的具有n個元素的正整數序列arr和乙個正整數s,求序列中兩個不同位置的數a和b,使他們的和恰好等於s,輸出所有滿足條件的結果i和j。如序列arr 和正整數s 9,就有 4 5 和 3 6 本例最簡單的方法就是利用二重迴圈列舉所有的可能性,得出結果。但是這樣做的時間複雜度...

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 級別。但是可以針對序列遞增這一條進行優化 對這個有...