题目描述
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.
给一个整数数组,找出其中三个元素组成三元组,使得三个元素之和为0
找出所有符合条件的三元组,且不可以重复
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路
对比第一题Two Sum的思路:先假定已经确定了其中一个数,再去寻找另一个数
本题也可以借鉴一点这个思想:先将数组从小到大排序,
假定一个基数base作为第一个元素,再在剩下的数组元素中通过双指针找到符合条件的另外两个元素,
以这个基数为第一个元素的情况都找出来后,再移动base指针,继续上述步骤,知道找到所有可能的三元组
注意:
- base指针的范围是[0 , nums.lengh-2)
- 双指针指的是:左指针初始是base的下一个元素,右指针初始是数组最后一个元素。
左右指针根据对三元素之和与0的关系的判断,决定如何移动:
(1)三元素和等于0:则左右指针都可以移动一步(左指针向右移动,右指针向左移动)
(2)三要素和大于0:需要把和调小点,所以只移动右指针
(3)三要素和小于0:需要把和调大点,所以只移动左指针
该base的所有情况都找完后,向右移动base,继续上述操作 - 双指针和base移动时都要注意排除重复情况,即如果移动一步后和上一步的元素值相同,要接着移动!!!
实现
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//res用来存放最终三元组列表
ArrayList<List<Integer>> res=new ArrayList<List<Integer>>();
//边界情况,直接返回空列表
if(nums.length<=2 || nums==null) return res;
//先将数组排序(小到大)
Arrays.sort(nums);
int i=0;
while(i<nums.length-2){
int base=nums[i]; //base基数
int left=i+1; //基数之后的第一个,左指针
int right=nums.length-1; //数组最后一个,右指针
while(left<right){
int sum=base+nums[left]+nums[right];
//若sum正好等于0,符合条件,把三个元素插入三元组,再插入到结果列表。再移动指针查找下一个三元组
if(sum==0){
//存放三元组的列表
LinkedList<Integer> list=new LinkedList<Integer>();
list.add(base);
list.add(nums[left]);
list.add(nums[right]);
res.add(list);
//移动指针,查找下一个符合条件的三元组
left=moveRight(nums,left+1);
right=moveLeft(nums,right-1);
}
//若sum大于0,需要调小,右指针向左移动
else if(sum>0){
right=moveLeft(nums,right-1);
}
//若sum小于0,需要调大,左指针向右移动
else{
left=moveRight(nums,left+1);
}
}
//找完一个基数,换下一个,向后移动基数指针
i=moveRight(nums,i+1);
}
return res;
}
//指针右移函数
public int moveRight(int[] nums,int left){
while(left==0 || (left<nums.length && nums[left]==nums[left-1])){
left++;
}
return left;
}
//指针左移函数
public int moveLeft(int[] nums,int right){
while(right==nums.length-1 || (right>=0 && nums[right]==nums[right+1])){
right--;
}
return right;
}
}
提交结果:
Time Submitted Status Runtime Memory Language
2 minutes ago Accepted 48 ms 46.6 MB java
时间复杂度O(n^2),好像有点慢