Problem: 18. 四数之和
题目
给你一个由 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
-109 <= nums[i] <= 109
-109 <= target <= 109
思路
和15.三数之和 (opens new window)是一个思路,都是使用双指针法, 基本解法就是在15.三数之和 (opens new window)的基础上再套一层for循环。
但是有一些细节需要注意,例如: 不要判断nums[k] > target 就返回了,三数之和 可以通过 nums[i] > 0 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。比如:数组是[-4, -3, -2, -1],target是-10,不能因为-4 > -10而跳过。但是我们依旧可以去做剪枝,逻辑变成nums[i] > target && (nums[i] >=0 || target >= 0)就可以了。
15.三数之和 (opens new window)的双指针解法是一层for循环num[i]为确定值,然后循环内有left和right下标作为双指针,找到nums[i] + nums[left] + nums[right] == 0。
四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况
解题方法
双指针法
复杂度
时间复杂度:
O(n^3)
空间复杂度:
O(1)
Code
Java
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
//排序
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList<>();
if(nums[0] > 0 && nums[0] > target){
return result;
}
int i, j, left, right;
for(i = 0; i < nums.length; i++){
if(i>0 && nums[i] == nums[i-1]){
continue;
}
for(j = i+1; j < nums.length; j++){
if(j > i+1 && nums[j] == nums[j-1]){
continue;
}
left = j+1;
right = nums.length-1;
while(right > left){
long sum = nums[i] + nums[j] + nums[left] + nums[right];
if(sum < target){
left++;
} else if (sum > target){
right--;
} else {
List<Integer> l = new ArrayList<>();
l.add(nums[i]);
l.add(nums[j]);
l.add(nums[left]);
l.add(nums[right]);
result.add(l);
//去重
while(left < right && nums[left] == nums[left+1]){
left++;
}
while(left < right && nums[right] == nums[right-1]){
right--;
}
left++;
right--;
}
}
}
}
return result;
}
}