Leetcode刷题(二十三)

四数之和(Medium)

给你一个由 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 


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



 示例 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<= nums[i] <= 10-10<= target <= 10Related Topics 数组 双指针 排序  1841  0

思路分析

这道题和本专栏前面的文章Leetcode刷题(二十)——最接近的三数之和十分相似,都是使用了双指针的方法,考虑的优化时间复杂度所考虑的方向也是相同的,但是这里要注意的是避免重复的判断逻辑要捋清楚,我就在判断四数之和与target的大小部分卡了很久,最后发现是因为判断之间的逻辑错误,最开始用的是:

                    if (sum == target) {

                    }
                    if (sum < target){

                    }else {

                    }

总是会缺少一下有效组合,通过debug发现,如果过sun==target的情况下,虽然不会进入第二个if的判断之中,但同理就会进入else导致产生错误,所以我改成了:

                    if (sum == target) {

                    }else if (sum < target){

                    }else {

                    }

同时要注意int类型的最大值,他在测试用例中出现了四个数相加超过了int类型最大值的情况。为了解决这个问题我是用了最大值更大的long类型。

代码实现

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public List<List<Integer>> fourSum(int[] num, int target) {
        long[] nums = new long[num.length];
        for (int x = 0; x < num.length; x++){
            nums[x] = num[x];
        }
        Arrays.sort(nums);
        Arrays.sort(num);
        List<List<Integer>> result = new ArrayList<>();
        for (int i = 0; i < nums.length-3; i++){

            for (int j = i + 1; j < nums.length-2; j++){
                int left = j + 1;
                int right = nums.length - 1;
                while (left < right){
                    long max = nums[i] + nums[j] + nums[right] + nums[right - 1];
                    long min = nums[i] + nums[j] + nums[left] + nums[left + 1];
                    if (target > max) break;
                    if (target < min) break;
                    long sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if (sum == target) {
                        result.add(Arrays.asList(num[i], num[j], num[left], num[right]));
                        while (left < right && nums[left] == nums[left + 1]) left++;
                        while (left < right && nums[right] == nums[right - 1]) right--;
                        left++;
                        right--;
                    }else if (sum < target){
                        left++;
                        while (left < right && nums[left] == nums[left - 1]) left++;
                    }else {
                        right--;
                        while (left < right && nums[right] == nums[right + 1]) right--;
                    }
                }
                while (j < nums.length-2 && nums[j]==nums[j+1]) j++;

            }
            while (i < nums.length-3 && nums[i]==nums[i+1]) i++;
        }

        return result;

    }
}
//leetcode submit region end(Prohibit modification and deletion)

个人笔记

在 Java 中,当一个整数的值超过其类型的最大值时,会发生称为“整数溢出”的现象。对于 int 类型,其最大值是 2,147,483,647(即 Integer.MAX_VALUE)。如果在加法运算中 int 类型的值超过这个界限,结果会“环绕”回该数据类型能表示的最小值,并继续计数。

具体来说,如果 int 类型的值在加法运算中溢出,它会从 -2,147,483,648(Integer.MIN_VALUE)开始,继续递增。这是因为 Java 中的整数类型使用的是补码表示法,所以当值超过最大值时,会发生环绕。

示例
假设你有两个 int 类型的值:

int a = Integer.MAX_VALUE; // 2,147,483,647
int b = 1;

如果你将它们相加:

int result = a + b;

结果 result 将会是 -2,147,483,648(即 Integer.MIN_VALUE),因为 a + b 的真实结果 2,147,483,648 超出了 int 类型可以表示的范围,导致整数溢出。

处理整数溢出
为了避免或处理整数溢出的问题,你可以采取以下措施:

使用更大的数据类型:比如使用 long 类型,它有更大的范围(-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807)。

使用 Math.addExact() 方法:在 Java 8 及以上版本中,Math 类提供了一些精确的算术方法,如 addExact(),这些方法在溢出时会抛出 ArithmeticException 异常,而不是让结果环绕。

try {
    int result = Math.addExact(a, b);
} catch (ArithmeticException e) {
    System.out.println("Integer overflow occurred");
}

通过采用这些方法,你可以更有效地管理和避免整数溢出的问题。

你可能感兴趣的:(Leetcode刷题实录,leetcode,算法)