题目:
给定一个包含n个整数的数组,在数组中是否存在a、b、c元素使得a + b + c = 0?找出数组中所有唯一的三胞胎,它们的和为零
注意:不能包含重复的三元组。
Given an array nums
of n integers, are there elements a, b, c in nums
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.
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is:[ [-1, 0, 1], [-1, -1, 2] ]
参考:
https://www.cnblogs.com/wangkundentisy/p/9079622.html
方法:
方法1:
先得到所有三个数不重复的组合,再每个组合求是否和为0,不为0则删除
果然超时了。。。在写出三个for的时候我眉头一皱发现事(肯)情(定)有(超)点(时)不(了)对 TAT
方法2:
先对数组进行排序
从第一个数nums[i]开始,寻找相加等于-nums[i](或者说与nums[i]相加等于0的两个数),寻找的方法为:
分别放两个指针,leftLoc=i+1,rightLoc=nums.length-1
循环条件:leftLoc<rightLoc
步骤:
1. 三数相加,如果等于0:将数组加入到结果re中,并将两个指针都往中间走
2. 如果结果小于0,则表示结果偏小,将leftLoc往中间走
3. 如果结果大于0,则表示结果偏大,将rightLoc往中间走
【注意】由于要求不能有重复,所以在遍历数组中的每个数,以及,将两个指针往中间挪动的时候,需要注意,如果所处的数不是边界值,则比较其当前值与上一个值是否相同,如果相同,则直接跳过——在挪动过程中也需要判断leftLoc<rightLoc,以防越界
(举的例子中没有相加可以为0的,只是举例说明位置挪动的方式)如1 1 2 2 3 4 5 6 6 6,在整体遍历时,如果对第一个1进行了查找,则第二个1直接跳过;在进行指针挪动时,如果左指针在第一个2的位置,则下一个左指针的位置应该为3,;如果右指针在最右的6的位置,则下一个右指针的位置应该为5的位置
代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> re = new LinkedList<List<Integer>>();
Arrays.sort(nums);
for(int i=0;i<nums.length-2;i++) {
// 跳过重复值
if(i!=0 && nums[i]==nums[i-1]) {
continue;
}
// 左右指针位置
int leftLoc = i+1;
int rightLoc = nums.length-1;
// 进入循环
while(leftLoc<rightLoc) {
int temp = nums[i]+nums[leftLoc]+nums[rightLoc];
// 如果相加为0
if(temp==0) {
List<Integer> t = new LinkedList<Integer>();
t.add(nums[i]);
t.add(nums[leftLoc]);
t.add(nums[rightLoc]);
re.add(t);
// 左右指针在进行跳过重复时 都要先自己挪动一步
// 因为在当前位置 不符合nums[leftLoc]==nums[leftLoc-1]
// 当然也阔以自己改成其他的条件~
// 下面两种情况中同理
leftLoc++;
while(leftLoc<rightLoc && nums[leftLoc]==nums[leftLoc-1]) {
leftLoc++;
}
rightLoc--;
while(leftLoc<rightLoc && nums[rightLoc]==nums[rightLoc+1]) {
rightLoc--;
}
}else {
// 相加小于0 挪左指针
if(temp<0) {
leftLoc++;
while(leftLoc<rightLoc && nums[leftLoc]==nums[leftLoc-1]) {
leftLoc++;
}
}else
// 相加大于0 挪右指针
if(nums[i]+nums[leftLoc]+nums[rightLoc]>0){
rightLoc--;
while(rightLoc>leftLoc && nums[rightLoc]==nums[rightLoc+1]) {
rightLoc--;
}
}
}
}
}
return re;
}
}
// 超时的三个for循环 嘿嘿嘿
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> re = new LinkedList<List<Integer>>();
Arrays.sort(nums);
for(int i=0;i<nums.length-2;i++) {
if(((i>0 && nums[i]!=nums[i-1]) || i==0) && nums[i]<=0) {
for(int j=i+1;j<nums.length-1;j++) {
if(nums[j]!=nums[j-1] || j==i+1) {
for(int k=j+1;k<nums.length;k++) {
if(nums[k]!=nums[k-1] || k==j+1) {
if(nums[k]+nums[j]+nums[i]==0) {
List<Integer> temp = new LinkedList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[k]);
re.add(temp);
}
}
}
}
}
}
}
return re;
}