1. 程式人生 > >演算法Day2-三數之和

演算法Day2-三數之和

題目

給定n個整數的一個數組S,S中是否有元素a,b和c滿足a+b+c+0 ? 找出陣列中所有滿足加和為0的不同的三個數組合。
注意:(a,b,c)中的元素必須是非降序的排列方式(即a<=b<=c)
解決方案中給出的集合不能包含重複的三元組
例如,給定的陣列S={-1 0 1 2 -1 -4}
一個解決方案集合是
    {-1, 0, 1}
    {-1, -1 ,2}

解析

本題為第一天題目兩數之和的拓展,把2個變數變成了3個變數。對於一般的拓展問題,要通過一些轉換將其還原為已有的問題,才能更好的處理。
對於本題,我們稍微把等式修改一下, a + b + c = 0 => a + b = -c。
這個時候,問題就轉換為,尋找兩個變數 a 和 b ,使得其之和為 -c , 又回到了“兩數之和”的問題。

因為題目提到了可能出現重複解的問題,所以要注意“去重”。這次的程式碼的變化也體現在去重的方面。
1. 雙指標掃描的去重。例如對於 [-2, 0, 0, 2, 2]。我們期待的結果是[-2, 0, 2],如果不去重的話,結果就是[-2, 0, 2],[-2, 0, 2]。因為對於陣列的處理是先排序的,所以本種除重是判斷當前start指標值是否與前一個指標值相等,或者當前end指標值是否與後一個指標值相等,如果相等,那麼就不予考慮。
2. 外層迴圈去重。 比如[-2, -2, -2, 0, 2],包含三個-2。當在迴圈中處理完第一個 -2 以後,後面的兩個就沒有必要進行重複處理了。

完整程式碼

#include <iostream>
#include <vector> #include <map> #include <algorithm> using namespace std; vector< vector<int> > threeSum(vector<int> &num){ sort(num.begin(), num.end()); vector< vector<int> > result; int len = num.size(); for(int i=0; i<len; i++){ int
target = 0 - num[i]; int start = i + 1, end = len - 1; while(start < end){ if(num[start] + num[end] == target){ vector<int> solution; solution.push_back(num[i]); solution.push_back(num[start]); solution.push_back(num[end]); result.push_back(solution); start++; end--; //雙指標掃描的去重 while(start<end && num[start] == num[start-1]) start++;//如果下一個元素與上一個元素相等,那麼跳過 while(start<end && num[end] == num[end+1]) end--;//如果上一個元素和當前end相等,跳過這個 } else if (num[start] + num[end] < target){ start++; } else{ end--; } }//end while if(i<len-1){ //外層迴圈的去重 while(num[i] == num[i+1]) i++; } }//end for //下面是輸出 vector< vector<int> >::iterator iter1; for(iter1 = result.begin(); iter1 != result.end(); iter1++) { vector<int> vTemp = *iter1; vector<int>::iterator iter2; for(iter2 = vTemp.begin(); iter2 != vTemp.end(); iter2++) { cout<<*iter2<<' '; } cout<<endl; } return result; } void main() { int nums[] = {-1,0,1,2,-1,-4};//這裡修改陣列 vector<int> v; for(int i=0; i<sizeof(nums) / 4; i++){ v.push_back(nums[i]); } threeSum(v); }

學習筆記

  1. 對於int型陣列,使用 sizeof() 對其求長度,需要除以4。 對於sizeof()的C++Reference是這樣定義的:

The sizeof operator is a compile-time operator that returns the size, in bytes, of the argument passed to it.
sizeof(int): 4
sizeof(float): 4
sizeof(double): 8
sizeof(char): 1

sizeof()是求的位元組長度,int字元是四個位元組,所以在求int型陣列的時候需要除以它的單位位元組長度。

2.對於使用迭代器輸出 兩層vector 巢狀型資料結構內容,程式碼如下:

vector< vector<int> >::iterator iter1;
    for(iter1 = result.begin(); iter1 != result.end(); iter1++)
    {
        vector<int> vTemp = *iter1;
        vector<int>::iterator iter2;
        for(iter2 = vTemp.begin(); iter2 != vTemp.end(); iter2++)
        {
            cout<<*iter2<<' ';
        }
        cout<<endl;
    }