4Sum

2014.2.8 20:58

Given an array S of n integers, are there elements abc, 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.

Solution:

  Find all (a, b, c, d) in the array, such that a + b + c + d = target. No duplicates allowed.

  First we sort the array, and pick out a and d from both ends. Later, we do a linear scan from the interval between a and d to find out b and c.

  Here is how the scan is done:

    1. let iterators b and c be at both ends.

    2. if num[b] + num[c] > target, move c left by one position.

    3. if num[b] + num[c] < target, move b right by one position.

    4. if num[b] + num[c] = target, one solution is found.

    5. if b >= c, the scan is ended.

  Sorting the array requires O(n * log(n)) time, finding the solutions requires O(n^3) time.

  To ensure no duplicates appear in the result set, I used a map to verify duplication.

  Time complexity is O(n^3), space complexity is O(s), where s is the total number of solutions.

Accepted code:

  1 // 1AC, excellent!
  2 // #define MY_MAIN
  3 #include <algorithm>
  4 #include <cstdio>
  5 #include <map>
  6 #include <string>
  7 #include <vector>
  8 using namespace std;
  9 
 10 class Solution {
 11 public:
 12     vector<vector<int> > fourSum(vector<int> &num, int target) {
 13         int n;
 14         int a, b, c, d;
 15         int s;
 16         vector<int> vtmp;
 17         char str[100];
 18         
 19         for (n = 0; n < (int)result.size(); ++n) {
 20             result[n].clear();
 21         }
 22         result.clear();
 23         signs.clear();
 24         vtmp.clear();
 25 
 26         // sort the array first
 27         sort(num.begin(), num.end());
 28         n = (int)num.size();
 29         for (a = 0; a < n; ++a) {
 30             for (d = a + 3; d < n; ++d) {
 31                 if (num[a] + num[d - 2] + num[d - 1] + num[d] < target) {
 32                     // too small
 33                     continue;
 34                 }
 35                 if (num[a] + num[a + 1] + num[a + 2] + num[d] > target) {
 36                     // too large
 37                     continue;
 38                 }
 39                 
 40                 b = a + 1;
 41                 c = d - 1;
 42                 s = target - num[a] - num[d];
 43                 while (true) {
 44                     if (b >= c) {
 45                         // edge is crossed
 46                         break;
 47                     }
 48                     if (num[b] + num[c] < s) {
 49                         ++b;
 50                     } else if (num[b] + num[c] > s) {
 51                         --c;
 52                     } else {
 53                         str[0] = 0;
 54                         // create a digital sign to detect duplicates.
 55                         sprintf(str, "%d%d%d%d", num[a], num[b], num[c], num[d]);
 56                         string ss = string(str);
 57                         if (signs.find(ss) == signs.end()) {
 58                             signs[ss] = 1;
 59                             vtmp.clear();
 60                             vtmp.push_back(num[a]);
 61                             vtmp.push_back(num[b]);
 62                             vtmp.push_back(num[c]);
 63                             vtmp.push_back(num[d]);
 64                             result.push_back(vtmp);
 65                         }
 66                         ++b;
 67                         --c;
 68                     }
 69                 }
 70             }
 71         }
 72         
 73         return result;
 74     }
 75 private:
 76     vector<vector<int> > result;
 77     map<string, int> signs;
 78 };
 79 
 80 #ifdef MY_MAIN
 81 int main()
 82 {
 83     int target;
 84     vector<int> num;
 85     int n;
 86     int tmp;
 87     Solution solution;
 88     vector<vector<int> > result;
 89     int i, j;
 90     
 91     while (scanf("%d%d", &n, &target) == 2) {
 92         num.clear();
 93         for (i = 0; i < n; ++i) {
 94             scanf("%d", &tmp);
 95             num.push_back(tmp);
 96         }
 97         result = solution.fourSum(num, target);
 98         printf("A solution set is:\n");
 99         for (i = 0; i < (int)result.size(); ++i) {
100             printf("(%d", result[i][0]);
101             for (j = 1; j < 4; ++j) {
102                 printf(", %d", result[i][j]);
103             }
104             printf(")\n");
105         }
106         printf("\n");
107     }
108     
109     return 0;
110 }
111 #endif

 

 posted on 2014-02-08 21:15  zhuli19901106  阅读(205)  评论(0编辑  收藏  举报