题目:3Sum 4个数的和
难度:中等
Given an array nums
of n integers and an integer target
, are there elements a, b, c, and d in nums
such that a + b + c + d = target
? Find all unique quadruplets in the array which gives the sum of target
.
Note:
The solution set must not contain duplicate quadruplets.
Example:
Given array nums = [1, 0, -1, 0, -2, 2], and target = 0. A solution set is: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
题意解析:
给定一个包含 n 个整数的数组 nums
和一个目标值 target
,判断 nums
中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target
相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
解题思路一:
跟三个数的和的思路类似,以一个数字为基准进行循环,然后剩下的三个数字再进行这样的操作,以第一个数字为基准进行循环,剩下的两个分别作为基准元素的后一个元素和最后一个元素,然后进行相加和目标元素进行比较。
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> lists = new ArrayList<>();
int n = nums.length;
for (int i = 0; i < n; i++) {
if (i > 0 && (nums[i]==nums[i-1]))
continue;
for (int j = i+1; j < n; j++) {
if (j > i+1 && (nums[j]==nums[j-1]))
continue;
int l = j + 1, r = n - 1;
while (l < r){
int sum = nums[i] + nums[j] + nums[l] + nums[r];
if (sum > target){
r--;
} else if (sum == target){
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[l]);
list.add(nums[r]);
lists.add(list);
while(l+1 < n-1 && nums[l] == nums[l + 1]) l++;
while(r-1 > 0 && nums[r] == nums[r - 1]) r--;
l++;
r--;
} else {
l++;
}
}
}
}
return lists;
}
提交代码之后:
Runtime: 27 ms, faster than 68.33% of Java online submissions for 4Sum.
Memory Usage: 39.9 MB, less than 66.61% of Java online submissions for 4Sum.
解题思路二:
之前的方法都是从左边开始循环的,这样每次都要全部进行判断。这里我们选择第一个数i还是从左边第一个数开始,然后对一些边界值进行判断,如果num[i]*4>target,那么直接返回list,然后j我们取数组的最后一个元素,同理如果num[j]*4<target那么也是直接返回list,然后在i和j之间对其中的元素进行遍历即可。
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
Arrays.sort(nums);
int second = 0, third = 0, nexti = 0, nextj = 0;
for(int i=0, L=nums.length; i<L-3; i++) {
if(nums[i]<<2 > target) return list;
for(int j=L-1; j>i+2; j--) {
if(nums[j]<<2 < target) break;
int rem = target-nums[i]-nums[j];
int lo = i+1, hi=j-1;
while(lo<hi) {
int sum = nums[lo] + nums[hi];
if(sum>rem) --hi;
else if(sum<rem) ++lo;
else {
list.add(Arrays.asList(nums[i],nums[lo],nums[hi],nums[j]));
while(++lo<=hi && nums[lo-1]==nums[lo]) continue;
while(--hi>=lo && nums[hi]==nums[hi+1]) continue;
}
}
while(j>=1 && nums[j]==nums[j-1]) --j;
}
while(i<L-1 && nums[i]==nums[i+1]) ++i;
}
return list;
}
提交代码之后:
Runtime: 5 ms, faster than 97.72% of Java online submissions for 4Sum.
Memory Usage: 42.5 MB, less than 29.96% of Java online submissions for 4Sum.