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)
所有的Ksum问题都可以通过枚举一个元素,退化成K-1sum,k-2sum…最终变成2sum,然后用2sum的双指针算法(头指针,尾指针)在线性时间解决,也就是Ksum问题有一个o(n^(k-1))的通解。
版本一:o(n^3)
class Solution { public: vector<vector<int> > fourSum(vector<int> &num, int target) { vector<vector<int>> re; if(num.size() < 4){ return re; } sort(num.begin(), num.end()); for(int i = 0; i < num.size() - 3; ){ for(int j = i + 1; j < num.size() - 2; ){ int a = num[i]; int b = num[j]; int thisTarget = target - a - b; int k = j + 1; int l = num.size() - 1; while(k < l){ int sum = num[k] + num[l]; if(sum == thisTarget){ vector<int> thisRe; thisRe.push_back(a); thisRe.push_back(b); thisRe.push_back(num[k]); thisRe.push_back(num[l]); re.push_back(thisRe); k++; while(k < l && num[k] == num[k - 1]){ k++; } l--; while(l > k && num[l] == num[l + 1]){ l--; } } else if(sum > thisTarget){ l--; while(l > k && num[l] == num[l + 1]){ l--; } } else{ k++; while(k < l && num[k] == num[k - 1]){ k++; } } } j++; while(j < num.size() && num[j] == num[j - 1]){ j++; } } i++; while(i < num.size() && num[i] == num[i - 1]){ i++; } } return re; } };
AC.
尝试用空间换时间,加入hashtable,key为每个2-pair的sum,value为一个vector,储存所有和为sum的id-pair。复杂度o(n^2*k),k为建哈希表和查哈希表的复杂度,与数据和哈希表的结构有关。但是却超时。
版本二:o(n^2*k) 超时,好奇怪,求高人指点。
class Solution { public: unordered_map<int, vector<vector<int>>> hashTable; vector<vector<int>> re; vector<vector<int>> fourSum(vector<int> &num, int target) { if(num.size() < 4){ return re; } sort(num.begin(), num.end()); //build hashmap for(unsigned int i = 0; i < num.size(); ){ for(unsigned int j = i + 1; j < num.size(); ){ int sum = num[i] + num[j]; vector<int> thisPair; thisPair.push_back(i); thisPair.push_back(j); if(hashTable.find(sum) == hashTable.end()){//not found vector<vector<int>> pairs; pairs.push_back(thisPair); hashTable[sum] = pairs; } else{//found hashTable[sum].push_back(thisPair); } j++; while(j < num.size() && num[j] == num[j - 1]){ j++; } } i++; while(i < num.size() && num[i] == num[i - 1]){ i++; } } //search hashmap for(unsigned int i = 0; i < num.size(); ){ for(unsigned int j = i + 1; j < num.size(); ){ int a = num[i]; int b = num[j]; int thisTarget = target - a - b; if(hashTable.find(thisTarget) != hashTable.end()){//found vector<vector<int>> pairs = hashTable[thisTarget]; for(unsigned int k = 0; k < pairs.size(); k++){ int idx = pairs[k][0]; int idy = pairs[k][1]; if(idx > j){//not duplicated vector<int> thisRe; thisRe.push_back(a); thisRe.push_back(b); thisRe.push_back(num[idx]); thisRe.push_back(num[idy]); re.push_back(thisRe); } } } j++; while(j < num.size() && num[j] == num[j - 1]){ j++; } } i++; while(i < num.size() && num[i] == num[i - 1]){ i++; } } return re; } };