LeetCode 15. 3Sum
題目要求:給出一個整型數組S。找出裏面所有的a,b,c使得a+b+c=0,要求每組數據不能完全相同。
題目給出的框架如下:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
}
};
解題思路
3Sum與2Sum的思路是一致的,都是先進行排序,然後採用首尾兩個標記,然後向中間移動。
2Sum的情況
如果我們處理的是2Sum的話,對其進行排序後,用下標i指向0,下標j指向尾部,i和j的移動情況有以下三種:
- 如果nums[i]+nums[j]==0,則i和j必須同時向中間移動,只移動一個的話,相加得到的結果必然是要麼大於要麼小於;
- 如果nums[i]+nums[j]<0,那麼就只能增大nums[i]+nums[j]的值,只有i向右移動,nums[i]的值增大,兩者的和纔會增大;
- 同理,如果nums[i]+nums[j]>0,那麼只有j向中間移動,兩者之後纔有可能等於0。
- 最後需要注意的是,因爲要求每組結果不能完全相同,因此,在移動的過程中,如果元素相同,則需要跳過。
3Sum的情況
3Sum與2Sum的情況類似,具體做法如下:
- 固定一個數k,在它後面找出兩個數i=k+1和j=length-1,i和j不斷向中間移動,使得nums[i]+nums[j]=0-nums[k];
- k從0開始移動至length-3的位置(至少需要留兩個位置給i和j),這樣就能找出所有的元素使得nums[i]+nums[j]+nums[k]=0;
- 同時,爲了排除相同的結果,i,j,k移動的時候碰到相同的元素應當跳過;
- 此外,當nums[k]>0的時候可以提前結束搜索,因爲不可能存在3個大於0的數之和爲0。
代碼實現
代碼實現如下:
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int> > v;
if (num.size() == 0)
return v;
sort(num.begin(), num.end());
for (int k = 0; k < num.size() - 2 && num[k] <= 0; ++k) {
if (k > 0 && num[k] == num[k - 1]) // 跳過重複元素
continue;
int i = k + 1, j = num.size() - 1;
while (i < j) {
if (num[i] + num[j] == 0 - num[k]) {
vector<int> temp;
temp.push_back(num[k]);
temp.push_back(num[i]);
temp.push_back(num[j]);
v.push_back(temp);
while (++i < j && num[i] == num[i - 1])
; // 跳過重複元素
while (i < --j && num[j] == num[j + 1])
; // 跳過重複元素
} else if (num[i] + num[j] > 0 - num[k])
--j;
else
++i;
}
}
return v;
}
};