leetcode(18. 四数之和)【中等】

文章介绍了一种解决寻找数组中四个整数之和等于给定目标值的问题的方法。通过排序数组,然后使用循环结合双指针来避免四重循环,优化了时间复杂度。在循环和指针移动中注意避免重复和超出目标值的情况。代码示例给出了具体的实现细节,并对可能出现的边界情况进行了处理。
摘要由CSDN通过智能技术生成

一、题目

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

  • 0 <= a, b, c, d < n
  • abcd 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]

示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

提示:

  • 1 <= nums.length <= 200
  • -10<sup>9</sup> <= nums[i] <= 10<sup>9</sup>
  • -10<sup>9</sup> <= target <= 10<sup>9</sup>

二、题解

仿照三数之和,四重循环肯定不可行,使用循环+双指针的模式,相比三数之和,多一次for循环,a、b两值使用for循环,在出现重复、本循环最小可能数都大于target时,continue;当a循环、某个a循环内的b循环,如果出现最大值小于target时,直接结束for循环,以减少资源消耗。

三、代码

import java.util.*;

public class fourSum_18 {
    public static List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        if(nums == null || nums.length < 4){
            return result;
        }
        Arrays.sort(nums);
        for(int i = 0; i < nums.length - 3; i++){  //第一个数
            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[nums.length-1] + nums[nums.length-2] + nums[nums.length-3] < target){ //本索引开头的数构成的最大组合小于目标数,直接进行下一次循环
                continue;
            }
            for(int j = i + 1; j < nums.length - 2; j++){ //第二个数
                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[nums.length-1] + nums[nums.length-2] < target){ //本索引开头的数构成的最大组合小于目标数,直接进行下一次循环
                    continue;
                }
                // 双指针 第三、第四个数
                int c = j + 1, d = nums.length - 1;
                while(c < d){
                    long sum = nums[i] + nums[j] + nums[c] + nums[d];
                    if(sum == target) {
                        result.add(Arrays.asList(nums[i], nums[j], nums[c], nums[d]));
                        // c ,d 与 相邻相同
                        while (c < d && nums[c] == nums[c + 1]) {
                            c++;
                        }
                        c++;
                        while (c < d && nums[d] == nums[d - 1]) {
                            d--;
                        }
                        d--;
                    }else if(sum < target){
                        c++;
                    }else{
                        d--;
                    }
                }
            }
        }
        return result;
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String[] num = sc.nextLine().split(",");
        int nums[] = new int[num.length];
        for(int i = 0; i < num.length; i++){
            nums[i] = Integer.valueOf(num[i]);
        }
        Scanner n = new Scanner(System.in);
        int target = sc.nextInt();
        System.out.println(fourSum(nums,target));
    }
}

四、结果

在这里插入图片描述

五、总结

  • 四个数相加可能会出现超出int表示范围的情况
  • 避免临近相同,而判断的语句应当写明大于初始指针所在位置,不然出现重复,如:2,2,2,2,2 8对应的唯一结果[[2,2,2,2]]也会因为消重错误没有结果输出。如下语句,笔者通过前写的是j>i,该用例未通过。
if (j > i + 1 && nums[j] == nums[j - 1]) {  //与前一个相同,跳过该数
	continue;
}

六、说明

  本文章仅用于记录个人做题记录
  由于本人是个小菜鸡(实锤),题目解法并非最优,且解题过程中参考(抄袭)各大佬解题方法,望见谅。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值