15. 3Sum && 16 sum closet && 18 4sum

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值