2014.2.8 20:58
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.
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