Leetcode | 3Sum

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:
Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},

A solution set is:
(-1, 0, 1)
(-1, -1, 2)

主要在去重方面走了弯路。思路同Two sum.

从num中取出一个数,就要把它的所有和为0的组合找出来。

找到一组之后,找下一组,i++,j--,但是要注意去重。

取出一个数的时候,就从它后面开始找其他两个数,因为在他之间的数已经找过了。 i = k + 1; 

确定范围之后,下一个k必须要忽略相同的数(Line 12) num[k] != num[k+1],k++。

 1     vector<vector<int> > threeSum(vector<int> &num) {
 2         vector<vector<int> > ret;
 3         if (num.size() < 3) return ret;
 4         
 5         vector<int> v;
 6         sort(num.begin(), num.end());
 7         
 8         for (int k = 0; k < num.size(); ++k) {
 9             // get num[k], search in [k + 1, n - 1]
10             int i = k + 1, j = num.size() - 1;
11             
12             // ignore duplicate num[k]
13             while (k < num.size() - 1 && num[k] == num[k + 1]) k++;
14             
15             while (j > i) {
16                 int s = num[i] + num[j];
17 
18                 if (s == -num[k]) {
19                     v.push_back(num[i]);
20                     v.push_back(num[k]);
21                     v.push_back(num[j]);
22                     sort(v.begin(), v.end());
23                     ret.push_back(v);
24                     v.clear();
25                     
26                     // continue to find another match
27                     i++;
28                     while (i <= j && num[i] == num[i - 1]) i++;
29                     j--;
30                     while (j >= i && num[j] == num[j + 1]) j--;
31                 } else if (s > -num[k]) {
32                     j--;
33                 } else {
34                     i++;
35                 }
36             }
37         }
38         
39         return ret;
40     }

写得简洁一点。

 1 class Solution {
 2 public:
 3     vector<vector<int> > threeSum(vector<int> &num) {
 4         vector<vector<int> > ans;
 5         if (num.empty()) return ans;
 6         sort(num.begin(), num.end());
 7         int n = num.size();
 8         for (int i = 0; i + 2 < n; ) {
 9             int target = -num[i]; 
10             for (int j = i + 1, k = n - 1; j < k; ) {
11                 int sum = num[j] + num[k];
12                 if (sum == target) { // sum + num[i] == 0
13                     vector<int> tmp = {num[i], num[j], num[k]};
14                     sort(tmp.begin(), tmp.end());
15                     ans.push_back(tmp);
16                     for (++j; j < k && num[j] == num[j - 1]; ++j); // ignore dups
17                     for (--k; k > j && num[k] == num[k + 1]; --k);
18                 } else if (sum < target) {
19                     j++;
20                 } else {
21                     k--;
22                 }
23             }
24             for (++i; i + 2 < n && num[i] == num[i - 1]; ++i);
25         }
26         
27         return ans;
28     }
29 };

3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

和3 sum类似,就是在查找的时候,必须跟踪最小的差值。

 1 class Solution {
 2 public:
 3     int threeSumClosest(vector<int> &num, int target) {
 4         if (num.size() < 3) return INT_MAX;
 5         
 6         sort(num.begin(), num.end());
 7         int minDiff = INT_MAX, minSum = target;
 8         for (int k = 0; k < num.size(); ++k) {
 9             // get num[k], search in [k + 1, n - 1]
10             int i = k + 1, j = num.size() - 1;
11             
12             int t = target - num[k]; 
13             
14             while (j > i) {
15                 int s = num[i] + num[j];
16                 if (abs(s - t) < minDiff) {
17                     minDiff = abs(s - t);
18                     minSum = s + num[k];
19                 }
20                 if (s == t) {
21                     return target;
22                 } else if (s > t) {
23                     j--;
24                 } else {
25                     i++;
26                 }
27             }
28             
29             // ignore duplicate num[k]
30             while (k < num.size() - 1 && num[k] == num[k + 1]) k++;
31         }
32         
33         return minSum;
34     }
35 };

 4Sum

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:
Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

A solution set is:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)

3 sum类似,加了一层。244ms.

 1 class Solution {
 2 public:
 3     vector<vector<int> > fourSum(vector<int> &num, int target) {
 4         vector<vector<int> > ret;
 5         if (num.size() < 4) return ret;
 6         
 7         vector<int> v;
 8         sort(num.begin(), num.end());
 9         
10         for (int m = 0; m < num.size(); ++m) {
11             for (int k = m + 1; k < num.size(); ++k) {
12                 // get num[k], search in [k + 1, n - 1]
13                 int i = k + 1, j = num.size() - 1;
14                 int t = target - num[m] - num[k];
15                 // ignore duplicate num[k]
16                 while (k < num.size() - 1 && num[k] == num[k + 1]) k++;
17                 
18                 while (j > i) {
19                     int s = num[i] + num[j];
20     
21                     if (s == t) {
22                         v.push_back(num[m]);
23                         v.push_back(num[k]);
24                         v.push_back(num[i]);
25                         v.push_back(num[j]);
26                         sort(v.begin(), v.end());
27                         ret.push_back(v);
28                         v.clear();
29                         
30                         // continue to find another match
31                         i++;
32                         while (i <= j && num[i] == num[i - 1]) i++;
33                         j--;
34                         while (j >= i && num[j] == num[j + 1]) j--;
35                     } else if (s > t) {
36                         j--;
37                     } else {
38                         i++;
39                     }
40                 }
41             }
42             while (m < num.size() - 1 && num[m] == num[m + 1]) m++;
43         }
44         return ret;
45     }
46 };

 4 sum有O(n^2)的解法,leetcode的discuss后面有。但是那个代码760ms。按照同样的思路,用set来去重,也是760ms。

 1 class Solution {
 2 public:
 3     vector<vector<int> > fourSum(vector<int> &num, int target) {
 4         vector<vector<int> > ret;
 5         if (num.size() < 4) return ret;
 6         
 7         sort(num.begin(), num.end());
 8         
 9         map<int, vector<pair<int, int> > > sums;
10         
11         for (int i = 0; i < num.size(); ++i) {
12             for (int j = i + 1; j < num.size(); ++j) {
13                 sums[num[i] + num[j]].push_back(pair<int, int>(i, j));
14             }
15         }
16         
17         map<int, vector<pair<int, int> > >::iterator it;
18         vector<int> v;
19         set<vector<int> > r;
20         for (int i = 0; i < num.size(); ++i) {
21             for (int j = i + 1; j < num.size(); ++j) {
22                 int s = target - num[i] - num[j];
23                 if ((it = sums.find(s)) != sums.end()) {
24                     for (vector<pair<int, int>>::iterator it2 = it->second.begin(); 
25                             it2 != it->second.end(); ++it2) {
26                         if (it2->first <= j) continue;
27                         v.push_back(num[i]);
28                         v.push_back(num[j]);
29                         v.push_back(num[it2->first]);
30                         v.push_back(num[it2->second]);
31                         r.insert(v);
32                         v.clear();
33                     }
34                 }
35             }
36         }
37         
38         for (set<vector<int> >::iterator it = r.begin(); it != r.end(); it++) {
39             ret.push_back(*it);
40         }
41         return ret;
42     }
43 };
原文地址:https://www.cnblogs.com/linyx/p/3716788.html