public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
if(nums.length<=2)
return res;
Arrays.sort(nums);
for(int i=0;i<nums.length-1;i++){
if(nums[i]>0)
break;
if(i>0&&nums[i]==nums[i-1])//这里也是避免重复
continue;
int left=i+1,right=nums.length-1;
while(left<right){
if(nums[left]+nums[right]==(-nums[i])){
List<Integer> temp = new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[left]);
temp.add(nums[right]);
res.add(temp);
left++;
right--;
while(left<right&&nums[left]==nums[left-1])
left++;//这两个while循环就是防止重复的组合
while(left<right&&nums[right]==nums[right+1])
right--;
}
else if(nums[left]+nums[right]>(-nums[i]))
right--;
else
left++;
}
}
return res;
}
Given an array S of n integers, are there elements a, b, c in S 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.
For example, given array S = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
解题思路:
先对数组进行排序(从小到大),然后从前向后遍历,相当于每次确定一个数,然后再在后面的数字里着是否有和为-nums[i]的组合(也就是2sum,两个index,一个是左边的指针,一个是右边的,都向中间移动)。注意的地方:
1. 其实遍历到倒数第三个数就可以,因为后面就不够三个数(但是其实就不满足循环里left<right的条件会自动退出)
2. 如果nums[i]>0就可以退出,因为经过排序的数组后面只会越来越大
3. 注意用于暂存的Arraylist的new的位置,一定要在if语句里面,不然一个for循环里面有可能有多个满足条件的组合
4. 题目要求不能出现重复的组合,eg:[-2,0,0,2,2].如果不进行处理,会出现 [[-2,0,2],[-2,0,2]]这样的结果。所以每次找到新的组合之后更新left和right,但是需要进行判断,如果nums[left]或者nums[right]没有更新就要继续移动指针。
16. 3sum closet
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
和3sum思路类似,但是这里需要遍历所有的组合来寻找最接近的和,注意这里的接近也就是abs(sum-target)最小。所以最后sum有可能大于target也有可能小于target。一开始我只想到小于target,觉得大于target就跳出循环,但是如果target是3,sum=1和sum=4,虽然sum=4>target,但是更接近。
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int res=nums[0]+nums[1]+nums[nums.length-1];
int min=Math.abs(res-target);
for(int i=0;i<nums.length-2;i++){
int left=i+1,right=nums.length-1;
while(left<right){
int temp=nums[i]+nums[left]+nums[right];
if(temp==target)
return target;
if(Math.abs(temp-target)<min){
min=Math.abs(temp-target);
res=temp;
}
if(temp<target)
left++;
if(temp>target)
right--;
}
}
return res;
}
18 4sum
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0. A solution set is: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
if(nums.length<4)
return res;
Arrays.sort(nums);
for(int i=0;i<nums.length-2;i++){
if(i>0&&nums[i]==nums[i-1])
continue;
threeSum(nums,i,target-nums[i],res);
}
return res;
}
public void threeSum(int[] nums,int start,int target,List<List<Integer>> res){
for(int i=start+1;i<nums.length-1;i++){
if(i>(start+1)&&nums[i]==nums[i-1])
continue;
int left=i+1,right=nums.length-1;
while(left<right){
if((nums[i]+nums[left]+nums[right])==target){
List<Integer> temp = new ArrayList<Integer>();
temp.add(nums[start]);
temp.add(nums[i]);
temp.add(nums[left]);
temp.add(nums[right]);
res.add(temp);
left++;
right--;
while(left<right&&nums[left]==nums[left-1])
left++;
while(left<right&&nums[right]==nums[right+1])
right--;
}
else if((nums[i]+nums[left]+nums[right])<target)
left++;
else
right--;
}
}
}
}
思路:
先排序然后对每个数字使用3sum.