RJ Trujillo bd9928bdb1 algorithms: (3/4)Sum(Closest): Improve code readability
This just makes the code easier to follow.

Signed-off-by: RJ Trujillo <certifiedblyndguy@gmail.com>
2020-01-16 09:48:43 +08:00

190 lines
5.2 KiB
C++

// Source : https://oj.leetcode.com/problems/3sum/
// Author : Hao Chen
// Date : 2014-07-22
/**********************************************************************************
*
* Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?
* Find all unique triplets in the array which gives the sum of zero.
*
* Note:
*
* Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
* The solution set must not contain duplicate triplets.
*
* For example, given array S = {-1 0 1 2 -1 -4},
*
* A solution set is:
* (-1, 0, 1)
* (-1, -1, 2)
*
*
**********************************************************************************/
#include <stdio.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
/*
* Similar like "Two Number" problem, we can have the simlar solution.
*
* Suppose the input array is S[0..n-1], 3SUM can be solved in O(n^2) time on average by
* inserting each number S[i] into a hash table, and then for each index i and j,
* checking whether the hash table contains the integer - (s[i]+s[j])
*
* Alternatively, the algorithm below first sorts the input array and then tests all
* possible pairs in a careful order that avoids the need to binary search for the pairs
* in the sorted list, achieving worst-case O(n^n)
*
* Solution: Quadratic algorithm
* http://en.wikipedia.org/wiki/3SUM
*
*/
vector<vector<int> > threeSum(vector<int> &num) {
vector< vector<int> > result;
if(num.size() == 0 || num.size() == 1 || num.size() == 2) return result;
//sort the array, this is the key
sort(num.begin(), num.end());
int n = num.size();
for (int i=0; i<n-2; i++) {
//skip the duplication
if (i > 0 && num[i - 1] == num[i]) continue;
int a = num[i];
int low = i + 1;
int high = n - 1;
while (low < high) {
int b = num[low];
int c = num[high];
if (a + b + c == 0) {
//got the soultion
vector<int> v;
v.push_back(a);
v.push_back(b);
v.push_back(c);
result.push_back(v);
// Continue search for all triplet combinations summing to zero.
//skip the duplication
while(low < n - 1 && num[low] == num[low + 1]) low++;
while(high > 0 && num[high] == num[high - 1]) high--;
low++;
high--;
} else if (a+b+c > 0) {
//skip the duplication
while(high > 0 && num[high] == num[high - 1]) high--;
high--;
} else {
//skip the duplication
while(low < n - 1 && num[low] == num[low + 1]) low++;
low++;
}
}
}
return result;
}
//using combination method could meet <<Time Limit Exceeded>> error
vector<vector<int> > combination(vector<int> &v, int k);
bool isSumZero(vector<int>& v);
int sum(vector<int>& v);
vector<vector<int> > threeSum2(vector<int> &num) {
vector< vector<int> > result;
vector< vector<int> > r = combination(num, 3);
for (int i = 0; i < r.size(); i++) {
if (isSumZero(r[i])) {
result.push_back(r[i]);
}
}
return result;
}
bool isSumZero(vector < int>& v) {
return sum(v) == 0;
}
int sum(vector<int>& v) {
int s = 0;
for(int i = 0; i < v.size(); i++) {
s += v[i];
}
return s;
}
vector<vector<int> > combination(vector<int> &v, int k) {
vector<vector<int> > result;
vector<int> d;
int n = v.size();
for (int i = 0; i < n; i++) {
d.push_back( (i < k) ? 1 : 0 );
}
//1) from the left, find the [1,0] pattern, change it to [0,1]
//2) move all of the 1 before the pattern to the most left side
//3) check all of 1 move to the right
while(1) {
vector<int> tmp;
for(int x = 0; x < n; x++) {
if (d[x]) tmp.push_back(v[x]);
}
sort(tmp.begin(), tmp.end());
result.push_back(tmp);
//step 1), find [1,0] pattern
int i;
bool found = false;
int ones = 0;
for(i = 0; i < n - 1; i++) {
if (d[i] == 1 && d[i + 1] == 0) {
d[i] = 0; d[i + 1] = 1;
found = true;
//step 2) move all of right 1 to the most left side
for (int j = 0; j < i; j++) {
d[j] = ( ones > 0 ) ? 1 : 0;
ones--;
}
break;
}
if (d[i] == 1) ones++;
}
if (!found) {
break;
}
}
return result;
}
void printMatrix(vector<vector<int> > &matrix)
{
for(int i = 0; i < matrix.size(); i++) {
printf("{");
for(int j = 0; j < matrix[i].size(); j++) {
printf("%3d ", matrix[i][j]) ;
}
printf("}\n");
}
cout << endl;
}
int main()
{
//int a[] = { -1, 0, 1, 2, -1, 1, -4 };
int a[] = { -1, 1, 1, 1, -1, -1, 0,0,0 };
vector<int> n(a, a + sizeof(a)/sizeof(int));
vector< vector<int> > result = threeSum(n);
printMatrix(result);
return 0;
}