演算法Day2-三數之和
阿新 • • 發佈:2019-01-26
題目
給定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);
}
學習筆記
- 對於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;
}