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 };

 

你可能感兴趣的:(LeetCode)