这题其实不容易调通,难就难在对重复元素的排除上。比如说a[]={-2,0,0,2,2},只能输出一个[-2,0,2],但对于a[]={-4,-1,-1,0,1,2,3},必须要输出2个: [-1,-1,2]和[-1,0,1],而对于a[]={0,0,0,0},又只能输出一个[0,0,0]。
注意:
1) 此题不存在O(nlogn)的解法。我一开始设想了一个解法是用两个指针p1,p2,一前一后。假设两个指针对应数和为sum,中间那个数用binary search找-sum。如果找不到,并且sum>0,就p2--,否则p1++。
比如说,a[]={-7,-4,0,1,1,3},-7+3=-4找4找不到,p1++,-4+3=-1,找到了。
但这种方法是不对的。举个反例,a[]={-7,-4,-4,0,1,1,2,8},-7+8=1,此时要p2--,但p2不能动,因为-4-4+8=0。这个binary search的方法不对的原因我认为是:如果找不到解,不能确定p1和p2怎么动,有可能只p1++,也可能只p2--,也可能p1++和p2--都要进行,所以这种试图两边往中间移动的思路不对。
2) 正解的方法是只锁定一边,也就是i++,然后从i+1到nums.size()-1里面用p1,p2,先算sum2=nums[p1]+nums[p2],然后sum2和-nums[i]比较,若sum2>-nums[i],则p2--; 若sum2<-nums[i],则p1++;如果两者相等,说明找到一个解。要注意此时应该再加一个while循环,把所有的解都弄出来。
这两行非常重要,里面又是两个小循环:
while ((++p1
它们表示将p1,p2移到不重复的地方,假设nums[1]=-1, p1~p2对应[-1,-1,0,1,2],此时找到一个解[-1,-1,2]。第一个while会将数组变成[-1,0,1,2],第二个while会将数组变成[-1,0,1],然后while(p1 但如果input数组是[-2,0,0,2,2,2,2]时,一开始while(p1 我一开始将上面两个循环写成 4) 此题避免重复解也可以用set或map。 又做了一遍,第二次的代码如下,其实跟第一次差不多。 3刷,发现自己以前水平太次了。 代码同步在 while ((p1
3) 最开始的 if ((i==0)||(nums[i]!=nums[i-1]))也可以防止重复解出现。如果nums[i-1]和nums[i]都是解的一部分也没关系,上次i-1的时候就已经输出了(因为已经i++),这是可以直接跳过nums[i]。#include
vector
class Solution {
public:
/**
* @param numbers: Give an array numbers of n integer
* @return: Find all unique triplets in the array which gives the sum of zero.
*/
vector
https://github.com/luqian2017/Algorithm