给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [ n u m s [ a ] , n u m s [ b ] , n u m s [ c ] , n u m s [ d ] ] [nums[a], nums[b], nums[c], nums[d]] [nums[a],nums[b],nums[c],nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 < = a , b , c , d < n 0 <= a, b, c, d < n 0<=a,b,c,d<n
a、b、c 和 d 互不相同
n u m s [ a ] + n u m s [ b ] + n u m s [ c ] + n u m s [ d ] = = t a r g e t nums[a] + nums[b] + nums[c] + nums[d] == target nums[a]+nums[b]+nums[c]+nums[d]==target
你可以按 任意顺序 返回答案 。
1 < = n u m s . l e n g t h < = 200 − 1 0 9 < = n u m s [ i ] < = 1 0 9 − 1 0 9 < = t a r g e t < = 1 0 9 1 <= nums.length <= 200\\ -10^9 <= nums[i] <= 10^9\\ -10^9 <= target<= 10^9 1<=nums.length<=200−109<=nums[i]<=109−109<=target<=109
和之前的3sum问题几乎一样,只不过这里的数字多了一个,同时数据的范围最大只有200
也就是说4层循环的暴力是一定TLE的,时间复杂度 O ( N 4 ) O(N^4) O(N4)。
如果借鉴3sum的思路来解决,也是先排序,然后固定ab,然后双指针找cd,整体的时间复杂度可以在 O ( N 3 ) O(N^3) O(N3)。
从时间复杂度的角度,已经不会有其他的策略可以优于这个思路。
但是以问题的最大数据规模,这个时间复杂度还是会有TLE的风险。
在最差的情况下,所有数据不重复,而且数据的长度达到最大规模,时间复杂度的上限就是 O ( N 3 ) O(N^3) O(N3).
但是对于某些特殊的情况下,还是可以进行加速。
和3sum一样的优化思路,
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
int n = nums.length;
List<List<Integer>> ans = new ArrayList();
for(int i = 0;i<n-3;i++){
if(i>0&&nums[i]==nums[i-1]) continue;
long a = (long)nums[i];
for(int j = i+1;j<n-2;j++){
if(j>i+1&&nums[j]==nums[j-1]) continue;
long b = (long)nums[j];
long tar = (long)target-a-b;
int l = j+1,r = n-1;
while(l<r){
long x = (long)nums[l]+(long)nums[r];
if(x==tar){
List<Integer> list = new ArrayList();
list.add((int)a);
list.add((int)b);
list.add(nums[l]);
list.add(nums[r]);
ans.add(list);
l++;r--;
while(l<r&&nums[l]==nums[l-1]) l++;
while(l<r&&nums[r]==nums[r+1]) r--;
}
else if(x<tar){
l++;
}
else{
r--;
}
}
}
}
return ans;
}
}
时间复杂度 O ( N 3 ) O(N^3) O(N3)
空间复杂度 O ( log N ) O(\log N) O(logN)
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
int n = nums.length;
List<List<Integer>> ans = new ArrayList();
for(int i = 0;i<n-3;i++){
if(i>0&&nums[i]==nums[i-1]) continue;
long a = (long)nums[i];
long sum = a;
sum += nums[i+1];
sum += nums[i+2];
sum += nums[i+3];
if(sum>target) break;
sum = a;
sum += nums[n-1];
sum += nums[n-2];
sum += nums[n-3];
if(sum<target) continue;
for(int j = i+1;j<n-2;j++){
if(j>i+1&&nums[j]==nums[j-1]) continue;
long b = (long)nums[j];
sum = a+b;
sum += nums[j+1];
sum += nums[j+2];
if(sum>target) break;
sum = a+b;
sum += nums[n-2];
sum += nums[n-1];
if(sum<target) continue;
long tar = (long)target-a-b;
int l = j+1,r = n-1;
while(l<r){
long x = (long)nums[l]+(long)nums[r];
if(x==tar){
List<Integer> list = new ArrayList();
list.add((int)a);
list.add((int)b);
list.add(nums[l]);
list.add(nums[r]);
ans.add(list);
l++;r--;
while(l<r&&nums[l]==nums[l-1]) l++;
while(l<r&&nums[r]==nums[r+1]) r--;
}
else if(x<tar){
l++;
}
else{
r--;
}
}
}
}
return ans;
}
}
时间复杂度 O ( N 3 ) O(N^3) O(N3)
空间复杂度 O ( log N ) O(\log N) O(logN)
Array
Sort
Two Pointer