Skip to content

Instantly share code, notes, and snippets.

@liruqi
Created April 11, 2016 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save liruqi/199dfd783a0b51909afc29d4e3762b7f to your computer and use it in GitHub Desktop.
Save liruqi/199dfd783a0b51909afc29d4e3762b7f to your computer and use it in GitHub Desktop.
/*
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