zoukankan      html  css  js  c++  java
  • 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 };
  • 相关阅读:
    Rotation Kinematics
    离职 mark
    PnP 问题方程怎么列?
    DSO windowed optimization 代码 (4)
    Adjoint of SE(3)
    IMU 预积分推导
    DSO windowed optimization 代码 (3)
    DSO windowed optimization 代码 (2)
    OKVIS 代码框架
    DSO windowed optimization 代码 (1)
  • 原文地址:https://www.cnblogs.com/linyx/p/3716788.html
Copyright © 2011-2022 走看看