0
点赞
收藏
分享

微信扫一扫

17、类似16题-18.四数之和

梦幻之云 2022-03-14 阅读 37

题目描述

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

思路:

和三数之和有一点不同!不能使用  > 0作为return条件;内层的for循环返回条件不定!

注意细节的处理

1)两层for循环,处理前两个数字;后两个数字使用双指针进行解决!

2)要理解:使用for循环枚举的时候,第二层的循环不用再从头找!只用从第一层循环的 i+1处开始即可,之前的情况已经全部包含!

3)Collections.sort(int[] arr);将数组排序

        if(!res.contains(ans)) res.add(ans);

    一个去重的方法! 

4)会有溢出问题,可以转换为 long型的,强转!

代码

1)排序 + 两层for循环 + 双指针

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);

        for(int i = 0;i < nums.length;i++){
            //处理和 三数之和不一样!
            //这里不能用 > 0作为返回标志!
            //if(nums[i] > target) return res;
            if(i > 0 && nums[i] == nums[i - 1]) continue;
            //可以往下走
            for(int j = i+1;j < nums.length;j++){
                //这里怎么处理,跳出内层的for循环
                //这里不能时return,应该是结束本次循环!修改i值
                //if(nums[j] >= target) continue;
                if(j > i + 1 && nums[j] == nums[j - 1]) continue;

                int m = j + 1;
                int n = nums.length - 1;
                while(m < n){
                    if(nums[i] + nums[j] + nums[m] + nums[n] > target) n--;
                    else if(nums[i] + nums[j] + nums[m] + nums[n] < target) m++;
                    else{
                        res.add(Arrays.asList(nums[i],nums[j],nums[m],nums[n]));//结果加到结果列表
                        //跳过重复的结果
                        while(m < n && nums[m] == nums[m + 1]) m++;
                        while(m < n && nums[n] == nums[n - 1]) n--;
                        //如果while判断过,就走到了边界;没判断也是边界;都需要往后移动
                        m++;
                        n--;
                    }
                }
            }
        }
        return res;
    }
}

2)加了两个边界条件的判定,优化很多!

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        int length = nums.length;

        for(int i = 0;i < nums.length - 3;i++){
            //处理和 三数之和不一样!
            //这里不能用 > 0作为返回标志!
            //if(nums[i] > target) return res;
            if(i > 0 && nums[i] == nums[i - 1]) continue;
            if((long)nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
            if((long)nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target){
                continue;
            }
  
            //可以往下走
            for(int j = i+1;j < nums.length - 2;j++){
                //这里怎么处理,跳出内层的for循环
                //这里不能时return,应该是结束本次循环!修改i值
                //if(nums[j] >= target) continue;
                if(j > i + 1 && nums[j] == nums[j - 1]) continue;
                if((long)nums[i] + nums[j] + nums[j+1] + nums[j+2] > target) break;
                if((long)nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target) continue;

                int m = j + 1;
                int n = nums.length - 1;
                while(m < n){
                    if((long)nums[i] + nums[j] + nums[m] + nums[n] > target) n--;
                    else if((long)nums[i] + nums[j] + nums[m] + nums[n] < target) m++;
                    else{
                        res.add(Arrays.asList(nums[i],nums[j],nums[m],nums[n]));//结果加到结果列表
                        //跳过重复的结果
                        while(m < n && nums[m] == nums[m + 1]) m++;
                        while(m < n && nums[n] == nums[n - 1]) n--;
                        //如果while判断过,就走到了边界;没判断也是边界;都需要往后移动
                        m++;
                        n--;
                    }
                }
            }
        }
        return res;
    }
}
举报

相关推荐

0 条评论