雙指標演算法以及各種應用
阿新 • • 發佈:2019-01-01
這裡雙指標指的是在同一個可迭代物件a中使用兩個迭代器(下面用i,j)。
反正就要能類似陣列這樣使用索引i, j來得到對應的值a[i], a[j],然後通過移動i跟j達到目的。下面以陣列為例
常見的使用方法有幾種:
1. i跟j在陣列的兩邊開始,用來把陣列分成兩部分
這個我們早遇到過了,我第一次遇見它被用來分成大於最左邊的數(基準數)跟小於最左邊的數兩部分。不過它結合了分治法導致你可能沒發現,它就是快速排序。當然快速選擇演算法中也是同樣。記得注意是括號裡是取小於等於,因為我們只把右邊小於(或大於)的數丟到另一邊。
//雙指標分組:將陣列分成>=temp以及<=temp的兩部分 int quickSort(int a[], int left, int right) { int i = left, j = right; int temp = a[left]; while(i < j) { // 這個可以不需要=,但浪費時間,比起換來換去排序好,不如不動就排序好 while(a[j] >= temp && i < j) j--; // i必須有=,否則才第一個就不會動 while(a[i] <= temp && i < j) i++; if(i < j) { //交換兩個數的函式,可以自己編寫或者加入algorithm標頭檔案使用 swap(a[i], a[j]); } } swap(a[left], a[i]); return i; } //分治法 void quick(int a[], int left, int right) { if(left >= right) return; int mid = quickSort(a, left, right); quick(a, left, mid-1); quick(a, mid + 1, right); }
當然,它還可以用來分奇偶數。
void division(int a[], int n) { int i = 0, j = n - 1; while(true) { while(i < j && a[i] % 2 == 1) i++; while(i < j && a[j] % 2 == 0) j--; if(i < j) { swap(a[i], a[j]); } } }
2. 快慢指標:求不定長陣列(連結串列)的中間元素(1/3,1/4都一樣)
思路:使用兩個指標,快指標速度是慢指標的2倍(若1/3則3倍,1/4則4倍),當快指標到達終點時,慢指標到達所求的點
List middle(List) { List qucik = a; List slow = a; while(quick != NULL && quick->next != NULL) { qucik = quick->next->next; slow = slow->next; } return slow; }
3. 固定距離指標: 求距離n的點
比如,求連結串列倒數第n個節點
思路:使用兩個指標,一個先走n步,然後一起走
List tailN(List a, int n)
{
List quick = a;
List slow = a;
for(int i = 0; i < n; i++)
{
quick = quick->next;
}
while(quick != NULL)
{
quick = quick->next;
slow = slow->next;
}
return slow;
}
4.兩邊微調:有序陣列找到兩個數的和
比如: 一個遞增序列中,找到兩個數的和為xx,返回他們的座標
思路:由於是遞增的,因此使用兩個指標,一個左邊i一個右邊j,小於xx則讓i向右,大於xx則讓j向左。
Result sumExist(int a[],int n, int sum)
{
int i = 0, j = n - 1;
Result result;
while(i < j)
{
if(a[i] + a[j] < sum)
i++;
else if (a[i] + a[j] > sum)
j--;
else
result.add(i);
result.add(j);
return result;
}
return NULL;
}