【LeetCode】解题18:4Sum

Problem 18: 4Sum [Medium]

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]
]

来源:LeetCode

解题思路

与15题3Sum类似。

  • 使用sort()对数组排序。
  • 双层遍历数组,并在第二层循环中数字nums[j]的后续数字nums[j+1]~nums[n-1]中,使用双指针法寻找和为target-nums[i]-nums[j]的两个数。
  • 在双层遍历以及双指针移动过程中注意跳过重复的数字。

减少执行用时的设计:

  • 在N<4时直接返回空。
  • 第一层遍历数组的当前数字nums[i]的四倍若大于target(即nums[i]*4 > target),则之后的循环中必不可能找到四数之和为target的结果,可以直接跳出循环。同理,第二层循环中,若当前数字nums[j]的三倍大于target-nums[i],则也可跳出循环。

排序的时间复杂度O(n log n),遍历时比15题多一层循环,因此遍历数组+双指针过程时间复杂度O(n3),总体时间复杂度O(n3)。

要点:排序双指针

Solution (Java)

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        int N = nums.length;
        if(N < 4) return result;
        Arrays.sort(nums);
        
        int last1 = nums[0], last2;
        int left, right, temp;
        for(int i = 0; i < N-3; i++){
            if(nums[i]*4 > target) break;
            if(nums[i] == last1 && i > 0) continue;
            last1 = nums[i];
            last2 = nums[i+1];
            for(int j = i+1; j < N-2; j++){
                if(nums[j]*3 > target - nums[i]) break;
                if(nums[j] == last2 && j > i+1) continue;
                last2 = nums[j];
                left = j+1;
                right = N-1;
                while(left < right){
                    if(nums[i] + nums[j] + nums[left] + nums[right] == target){
                        result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                        temp = nums[left];
                        while(++left < right && nums[left] == temp);
                    }
                    else if(nums[i] + nums[j] + nums[left] + nums[right] > target){
                        temp = nums[right];
                        while(--right > left && nums[right] == temp);
                    }
                    else{
                        temp = nums[left];
                        while(++left < right && nums[left] == temp);
                    }
                }
            }
        }
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值