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: 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]
]
Solution:
/*************************************************************************
> File Name: 3Sum.c
> Author:
> Mail:
> Created Time: 2016年07月12日 星期二 19时40分36秒
************************************************************************/
#include<stdio.h>
//wiki上有详细的分析,但是针对本问题解法有重复,https://en.wikipedia.org/wiki/3SUM
void swap(int *a, int left, int right) {
int temp = a[left];
a[left] = a[right];
a[right] = temp;
}
int partition(int *a, int left, int right) {
if (NULL==a || left<0 || right<=0 || left>=right)
return -1;
int pivot = a[(left + right) / 2];
while (left <= right) {
// find the date at left side shift to right side
while (left<=right && a[left]<pivot)
left++;
// find the data at right side shift to left side
while (left<=right && a[right]>pivot)
right--;
// swap
if (left <= right) {
swap(a, left, right);
left++;
right--;
}
}
return left;
}
void Qsort(int *a, int left, int right) {
if (NULL==a || left<0 || right<=0 || left>=right)
return;
int index = partition(a, left, right);
if (left < index-1)
Qsort(a, left, index-1);
if (index < right)
Qsort(a, index, right);
}
void quickSort(int *a, int len) {
Qsort(a, 0, len-1);
}
/**
* Return an array of arrays of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
int** threeSum(int* nums, int numsSize, int* returnSize) {
int i;
int size = 0;
int a, b, c, start, end;
quickSort(nums, numsSize);
int** res = (int**)malloc(sizeof(int*));
for (i = 0; i < numsSize - 2; i++) {
// in case of duplicate solutions
if(i > 0 && nums[i] == nums[i-1]) continue;
a = nums[i];
start = i + 1;
end = numsSize - 1;
while (start < end) {
b = nums[start];
c = nums[end];
//printf("== %d, %d, %d==\n", a, b, c);
if ((a + b + c) == 0) {
res = (int**)realloc(res, sizeof(int*) * (size + 1));
// output a, b, c;
res[size] = (int*)malloc(sizeof(int) * 3);
res[size][0] = a;
res[size][1] = b;
res[size][2] = c;
//printf("a, b, c: %d, %d, %d\n", a, b, c);
size++;
// in case of duplicate solutions
while(start < numsSize && nums[start] == b) start++;
// in case of duplicate solutions
while(end >= 0 && nums[end] == c) end--;
// Continue search for all triplet combinations summing to zero.
//end--;
} else if((a + b + c) > 0) {
end--;
} else {
start++;
}
}
}
*returnSize = size;
return res;
}
void test(int* a, int len) {
int i;
int l = 0;
int** res = threeSum(a, len, &l);
for(i = 0; i < l; i++) {
printf("[%d, %d, %d]\n", res[i][0], res[i][1], res[i][2]);
}
}
int main() {
printf("test a1: \n");
int a1[6] = {-1,0,1,2,-1,-4};
test(a1, 6);
printf("\n\n");
printf("test a2: \n");
int a2[15] = {-4,-2,-2,-2,0,1,2,2,2,3,3,4,4,6,6};
test(a2, 15);
return 0;
}
C++的解法:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
if(nums.size() < 3) return ans;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size() - 2; i ++) {
// in case of duplicate solutions
if(i > 0 && nums[i] == nums[i-1]) continue;
int a = nums[i];
int lf = i + 1;
int rt = nums.size() - 1;
while(lf < rt) {
int b = nums[lf];
int c = nums[rt];
if(0 == a + b + c) {
ans.push_back(vector<int> {a, b, c});
// in case of duplicate solutions
while(lf < nums.size() && nums[lf] == b) lf ++;
// in case of duplicate solutions
while(rt >= 0 && nums[rt] == c) rt --;
}
else if(a + b + c > 0) rt --;
else lf ++;
}
}
return ans;
}
};