3Sum

Given an array S of n integers, are there elements abc 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)

这道题有个难点,不能输出相同的结果。
如何保证不会输出相同的结果呢,开始想到的是每找到一个结果存起来后,再其后的查找过程中和已有的结果进行对比,当且仅当当前查找的前两个数与已有的所有结果都不相等时才去查找第三个数。这样肯定是可行的,但实现起来很麻烦,与已有结果比较的过程也很浪费时间。
好在题目本身提供了解题思路:题目要求输出结果数组必须按非降序排列。
那么很容易想到先把数组进行排序。然后发现了本题的思路,即第一个数、第二个数、第三个数对应的三重循环中,每结束当前数的一轮循环时,直接跳到下一个与当前数不相等的数进行下一轮循环,这样便可保证找到的结果不会重复。大家可以自己证明一下。
其次,在三重循环中分别设置 (1) nums[i] <= 0; (2) nums[i] + nums[j] <= 0;(3) nums[i] + nums[j] + nums[k] >= 0 ; 这三个进入循环的条件,可以提前终止对相应数的不必要的搜索。
C语言代码如下:
int cmp(const void *a, const void *b)
{
	return(*(int *)a-*(int *)b);
}

int** threeSum(int* nums, int numsSize, int* returnSize) {
	/* sort the array */
	qsort(nums, numsSize, sizeof(nums[0]), cmp);
	int i,j,k;
	int **result = (int **) malloc(sizeof(int *) * 1000);
	*returnSize = 0;
	/* find the 3 proper numbers */
	for(i = 0; i < numsSize - 2 && nums[i] <= 0; ){
		for(j = i + 1; j < numsSize - 1 && nums[i] + nums[j] <= 0; ){
			for(k = numsSize - 1; k > j && nums[i] + nums[j] + nums[k] >= 0; ){
				if(nums[i] + nums[j] + nums[k] == 0){
				if(!(result[(*returnSize)] = (int *)malloc(sizeof(int) * 3))) return NULL;
					result[(*returnSize)][0] = nums[i];
					result[(*returnSize)][1] = nums[j];
					result[(*returnSize)++][2] = nums[k];
				}
				k--;
				/* looking for the first unlike number */
				while(k > j && nums[k] == nums[k + 1])
					k--;
			}
			j++;
			/* looking for the first unlike number */
			while(j < numsSize - 1 && nums[j] == nums[j - 1])
				j++;
		}
		i++;
		/* looking for the first unlike number */
		while(i < numsSize - 2 && nums[i] == nums[i - 1])
			i++;
	}
	if(*returnSize == 0)
		return NULL;
	return result;
}


小结:
1)注意加入有效的循环控制条件(临界值),避免无谓的计算。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值