给你一个由 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 <= 10⁹
Related 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");
}
通过采用这些方法,你可以更有效地管理和避免整数溢出的问题。