【算法】4Sum 四数之和

文章目录

  • 4Sum 四数之和
    • 问题描述:
    • 分析
    • 代码
      • 加速
    • Tag

4Sum 四数之和

问题描述:

给你一个由 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<=200109<=nums[i]<=109109<=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一样的优化思路,

  • 每次固定的ab,一定不能和上一次的ab相等,否则就会出现重复的计算。
  • 如果连续的 a + b + c + d > t a r g e t a+b+c+d>target a+b+c+d>target,那么当前的ab就不可能找到一组符合条件的组合,可以提前break。
  • 如果 a + b + a [ n − 1 ] + a [ n − 2 ] < t a r g e t a+b+a[n-1]+a[n-2]a+b+a[n1]+a[n2]<target,说明当前枚举b可能小了,可以提前枚举下一个b。

代码

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)

Tag

Array

Sort

Two Pointer

你可能感兴趣的:(数据结构与算法,算法,数据结构)