[LeetCode] 18. 4Sum

题:https://leetcode.com/problems/4sum/

题目大意

从 数组nums ,从中选取 4个数,使得 4 数之和为 target。

思路

O(n3) 类似 3 sum

先取 2个数,然后 双指针方法

对于 重复的数字,可以使用 两种措施改进。

若 nums[i-1] == nums[i] 或 nums[j-1] == nums[j], 那么前面已经 遍历过 。

若 while(l<r && nums[r-1] == nums[r])
r–;
while(l<r && nums[l+1] == nums[l])
l++;
对双指针 跳过 重复


class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>>  res = new ArrayList();
        for(int i = 0 ; i < nums.length ; i++){
            if(i > 0 && nums[i-1] == nums[i])
                continue;
            for(int j = i+1; j < nums.length ;j++){
                if(j > i + 1 && nums[j-1] == nums[j])
                    continue;
                int l = j+1;
                int r = nums.length -1;
                while(l < r){
                    int tsum = nums[i] + nums[j] + nums[l] + nums[r];
                    if(tsum == target){
                        
                        List<Integer> eRes = new ArrayList();
                        eRes.add(nums[i]);
                        eRes.add(nums[j]);
                        eRes.add(nums[l]);
                        eRes.add(nums[r]);
                        res.add(eRes);
                        while(l<r && nums[r-1] == nums[r])
                            r--;
                        while(l<r && nums[l+1] == nums[l])
                            l++;
                        r--;
                        l++;
                    }
                    else if(tsum>target){
                        r--;
                    }else{
                        l++;
                    }
                }
            }
        }
        return res;
        
    }
}

O(n2)

使用 map 记录 每tsum。

然后,每次抽 两个数,看对应数 是否在 map中,并使用 res.contains(eRes) 来 去除重复。

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>>  res = new ArrayList();
        Map<Integer,List<Integer[]>> map = new HashMap();
        for(int i = 0 ; i < nums.length ; i++){
            for(int j = i + 1 ;j < nums.length ; j++){
                int tsum = nums[i] + nums[j];
                if(map.get(tsum) == null)
                    map.put(tsum,new ArrayList());
                map.get(tsum).add(new Integer[]{i,j});
            }
        }
        for(int i = 0 ; i < nums.length ; i++){
            if(i > 0 && nums[i-1] == nums[i])
                continue;
            for(int j = i + 1 ;j < nums.length ; j++){
                if(j > i + 1 && nums[j-1] == nums[j])
                    continue;
                int remainder = target - nums[i] - nums[j];
                if(!map.containsKey(remainder))
                    continue;

                for(Integer[] iArr: map.get(remainder)){
                    int l = iArr[0];
                    int r = iArr[1];
                    if(j >= l)
                        continue;
                    List<Integer> eRes = new ArrayList();
                    eRes.add(nums[i]);
                    eRes.add(nums[j]);
                    eRes.add(nums[l]);
                    eRes.add(nums[r]);

                    if(!res.contains(eRes))
                        res.add(eRes);
                }
            }
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值