Created
April 11, 2016 15:40
-
-
Save liruqi/199dfd783a0b51909afc29d4e3762b7f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
249 / 282 test cases passed. | |
Status: Wrong Answer | |
Input: | |
[-2,0,5,-1,-5,5,3] | |
-2 | |
Output: | |
[[-5,-2,0,5],[-2,-1,0,1]] | |
Expected: | |
[[-5,-2,0,5]] | |
*/ | |
namespace numbers { | |
vector< pair<int,int> > sort_uniq_c(vector<int>& nums) { // sort | uniq -c | |
vector< pair<int,int> > cnted; | |
if (nums.size() == 0) { | |
return cnted; | |
} | |
sort(nums.begin(), nums.end()); | |
cnted.push_back(make_pair(nums[0],1)); | |
for (int i=1; i<nums.size(); i++) { | |
pair<int,int> & top = cnted[cnted.size() - 1]; | |
if (top.first == nums[i]) { | |
top.second += 1; | |
} else { | |
cnted.push_back(make_pair(nums[i],1)); | |
} | |
} | |
return cnted; | |
} | |
vector< vector<int> > _unique_three_sum(vector<pair<int,int> > & cnted, int dest) { | |
vector< vector<int> > res; | |
for (long ci=cnted.size() - 1; ci >=0; ci--) { | |
pair<int,int> cp = cnted[ci]; | |
if (cp.first * 3 < dest) { | |
break; | |
} | |
if (cp.first * 3 == dest) { | |
if (cp.second >= 3) { | |
vector<int> can; | |
can.push_back(cp.first); | |
can.push_back(cp.first); | |
can.push_back(cp.first); | |
res.push_back(can); | |
} | |
break; | |
} | |
int sum = cp.first * 2; | |
if (cp.second >= 2) { | |
for (long ai=ci - 1; ai >= 0; ai--) { | |
if (sum + cnted[ai].first == dest) { | |
vector<int> can; | |
can.push_back(cnted[ai].first); | |
can.push_back(cp.first); | |
can.push_back(cp.first); | |
res.push_back(can); | |
break; | |
} | |
} | |
} | |
sum = cp.first; | |
int bdest = dest - sum; | |
for (long bi = ci - 1; bi >= 0; bi --) { | |
pair<int,int> bp = cnted[bi]; | |
if (bp.first * 2 < bdest) { | |
break; | |
} | |
if (bp.first * 2 == bdest) { | |
if (bp.second >= 2) { | |
vector<int> can; | |
can.push_back(bp.first); | |
can.push_back(bp.first); | |
can.push_back(cp.first); | |
res.push_back(can); | |
} | |
break; | |
} | |
int cdest = bdest - bp.first; | |
for (long ai=bi - 1; ai >= 0; ai--) { | |
if (cnted[ai].first == cdest) { | |
vector<int> can; | |
can.push_back(cnted[ai].first); | |
can.push_back(bp.first); | |
can.push_back(cp.first); | |
res.push_back(can); | |
break; | |
} | |
} | |
} | |
} | |
return res; | |
} | |
vector< vector<int> > unique_three_sum(vector<int>& nums, int dest) { | |
vector< pair<int,int> > cnted = sort_uniq_c(nums); | |
return _unique_three_sum(cnted, dest); | |
} | |
int closest_three_sum(vector<int>& nums, int dest) { | |
sort(nums.begin(), nums.end()); | |
long res = INT_MAX; | |
vector< pair<int,int> > cnted = sort_uniq_c(nums); | |
for (long ci=cnted.size() - 1; ci >=0; ci--) { | |
pair<int,int> cp = cnted[ci]; | |
if (cp.second >= 3) { | |
if (abs(cp.first * 3 - dest) < abs(res - dest)) { | |
res = cp.first * 3; | |
} | |
} | |
if (cp.second >= 2) { | |
for (long ai=ci - 1; ai >= 0; ai--) { | |
if (abs(cp.first * 2 + cnted[ai].first - dest) < abs(res - dest)) { | |
res = cp.first * 2 + cnted[ai].first; | |
} | |
} | |
} | |
for (long bi = ci - 1; bi >= 0; bi --) { | |
pair<int,int> bp = cnted[bi]; | |
if (bp.second >= 2) { | |
if (abs(bp.first * 2 + cp.first - dest) < abs(res - dest)) { | |
res = bp.first * 2 + cp.first; | |
} | |
} | |
for (long ai=bi - 1; ai >= 0; ai--) { | |
if (abs(bp.first + cp.first + cnted[ai].first - dest) < abs(res - dest)) { | |
res = bp.first + cp.first + cnted[ai].first; | |
} | |
} | |
} | |
} | |
return res; | |
} | |
/* cnted 是一个递增的数组 | |
* pair first 为数值;pair sencond 为数量(假设均>=1) | |
*/ | |
vector< vector<int> > _unique_sum(vector<pair<int,int> >& cnted, map<int,int> & nidx, int startIdx, int dest, int depth) { | |
vector< vector<int> > res; | |
pair<int,int> & cp = cnted[startIdx]; | |
if (depth == 0) { | |
if (dest == 0) { | |
vector<int> can; | |
res.push_back(can); | |
} | |
return res; | |
} | |
if (startIdx >= cnted.size()) return res; | |
if (depth == 1) { | |
map<int,int>::iterator it = nidx.find(dest); | |
if (it == nidx.end() || it->second < startIdx) return res; | |
vector<int> can; | |
can.push_back(dest); | |
res.push_back(can); | |
return res; | |
} | |
if (cp.first * depth > dest) { | |
return res; | |
} | |
if (cnted[cnted.size() - 1].first * depth < dest) { | |
return res; | |
} | |
for (int c= min(cp.second, depth); c>=0; c--) { | |
// int sidx = (cp.second == c) ? startIdx + 1 : startIdx; | |
// cp.second -= c; | |
vector< vector<int> > subres = _unique_sum(cnted, nidx, startIdx + 1, dest - cp.first * c, depth - c); | |
// cp.second += c; | |
for (int subi=0; subi<subres.size(); subi++) { | |
vector<int> can = subres[subi]; | |
can.insert(can.begin(), c, cp.first); | |
res.push_back(can); | |
} | |
} | |
return res; | |
} | |
vector< vector<int> > unique_four_sum(vector<int>& nums, int target) { | |
vector< pair<int,int> > cnted = numbers::sort_uniq_c(nums); | |
map<int,int> nidx; | |
for (int i=0; i<nums.size(); i++) { | |
nidx[cnted[i].first] = i; | |
} | |
return numbers::_unique_sum(cnted, nidx, 0, target, 4); | |
} | |
}; | |
class Solution { | |
public: | |
vector<vector<int>> fourSum(vector<int>& nums, int target) { | |
return numbers::unique_four_sum(nums, target); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment