這是leetcode裏面點贊數比較多的題,難度不大但是不知道技巧會覺得難以解決。題幹很簡潔,從一個數組中找出和爲0的三個元素,組成一個三元組,返回不重複的所有滿足條件的三元組。這裏有兩個問題需要解決,怎樣才能從無序的數組中找出滿足條件的三元組,怎樣才能保證它們不重複。查看這題的討論區(Discuss欄)後,贊同數最多的那條令我恍然大悟。
從無序的數組中查找難度比較大,所以可以先將數組排序,形成增序數組,然後對於數組中的元素nums[i],假定它是滿足條件的三元組中最小的元素(i從0到nums.size()-3,因爲某個滿足條件的三元組中最小元素的元素在原數組中至多是第3大),則其他兩個元素之和應該是-nums[i]。在num[i]的右邊設置遊標lo爲i+1,hi爲nums.size()-1,如果nums[lo]和nums[hi]的和爲-nums[i],則找到了一個滿足條件的三元組,保存,然後lo減一,hi加一。如果nums[lo]+nums[hi]小於-nums[i],說明nums[lo]過小,則lo加一;否則nums[hi]過大,hi減一。
爲了解決重複問題,在取最小元素的過程中,遇到nums[i]和它前一個元素值相等的情況,跳過nums[i]。當找到一個滿足條件的三元組,lo減一之後,遇到nums[lo]和它前一個元素相等,lo繼續加一,直到不等,hi同理。
以下是實現代碼
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
if (nums.size() < 3)
return result;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size() - 2; i++) {
if (i != 0) {
if (nums[i] == nums[i - 1])
continue;
}
int twosum = 0 - nums[i];
int lo = i + 1, hi = nums.size() - 1;
while (lo < hi) {
if (nums[lo] + nums[hi] == twosum) {
vector<int> vec;
vec.push_back(-twosum);
vec.push_back(nums[lo]);
vec.push_back(nums[hi]);
result.push_back(vec);
lo++;
hi--;
while ((lo < hi)&&(nums[lo] == nums[lo - 1]))
lo++;
while ((lo < hi)&&(nums[hi] == nums[hi + 1]))
hi--;
} else {
if (nums[lo] + nums[hi] < twosum) {
lo++;
} else {
hi--;
}
}
}
}
return result;
}
};