三数之和
Posted onlyandonly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三数之和相关的知识,希望对你有一定的参考价值。
给定一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
这条题目应该是典型的算法优化题了吧。从方法到循环语句到判断条件,几乎每个地方都要写得完美才不会TLE,虽然我写得可能还是破绽百出。。。
碰到这种题目我都是一股脑地排列组合,也就是穷举。。。后来在循环里加了几个判断条件可以减少很多时间,但还远远不够。。后来从别人那里看到了使用左右指针的思路,不再需要排列组合,终于提交过了。。
这题主要的几个点:
1、不能有重复的三元组。遍历的时候判断一下跟上一个相不相同,相同就跳过。
2、返回数组的内存分配。一开始我算出了所有排列组合的数量,但是我不知道怎么总结出公式(我真是个智障)。。。然后爱咋咋地吧,直接分配了n*n个内存,勉强是提交过了。之后在别人的答案里发现了realloc函数,简直如获至宝啊哈哈哈哈!
a=(int **)realloc(a,sizeof(int *)*(size+1));
通过这样就可以动态分配内存了,原先内存里的内容也不会被覆盖掉。
3、算法。遍历就不提了,时间复杂度达到O(n^3),真的蠢。。主要是先取一个数,它的相反数就是我们要的target,然后就变成了twoSum,twoSum使用左右指针,每次只要o(n)的时间,最后时间复杂度只有O(n^2)。
/** * Return an array of arrays of size *returnSize. * Note: The returned array must be malloced, assume caller calls free(). */ int cmp(const void *a,const void *b) { return *(int *)a-*(int *)b; } int** threeSum(int* nums, int numsSize, int* returnSize) { int i,j,k; qsort(nums,numsSize,sizeof(int),cmp); int **a=0; int size=0; int size_2=numsSize-2; int target,l,r; for(i=0;i<size_2;i++) { if(nums[i]>0) break; if(i>0&&nums[i]==nums[i-1]) continue; target=0-nums[i]; l=i+1;r=numsSize-1; while(l<r) { if(nums[l]+nums[r]==target) { a=(int **)realloc(a,sizeof(int *)*(size+1)); a[size]=(int *)malloc(sizeof(int)*3); a[size][0]=nums[i]; a[size][1]=nums[l]; a[size][2]=nums[r]; size++; while(nums[l]==nums[l+1]&&l<r) l++; while(nums[r]==nums[r-1]&&l<r) r--; l++; r--; } else if(nums[l]+nums[r]>target) r--; else l++; } } *returnSize=size; return a; }
以上是关于三数之和的主要内容,如果未能解决你的问题,请参考以下文章
代码随想录算法训练营第7天 | ● 454.四数相加II ● 383. 赎金信 ● 15. 三数之和 ● 18. 四数之和 ● 总结