【算法】18. 四数之和(多语言实现)

142 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情


18. 四数之和:

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abcd 互不相同
  • 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

原题传送门:

leetcode.cn/problems/4s…


分析

  • 面对这道算法题目,二当家的陷入了沉思。
  • 第一反应就是暴力四层循环,但是据说会超时。
  • 如果是两数之和,在知道第一个数的情况下,第二个数也就固定了;
  • 四数之和在第一个数固定后,并不能固定第二个数,第三个数和第四个数,所以才需要四层循环。
  • 然而如果我们把数组先排序一下,在确定了前两个数之后,后两个数就有了关系,一个数越大,另一个数就需要越小,可以合并成一次循环。

题解

rust

impl Solution {
    pub fn four_sum(mut nums: Vec<i32>, target: i32) -> Vec<Vec<i32>> {
        let mut ans = Vec::new();
        let n = nums.len();
        if n < 4 {
            return ans;
        }
        nums.sort();
        for first in 0..n - 3 {
            if first > 0 && nums[first] == nums[first - 1] {
                continue;
            }
            if nums[first] as i64 + nums[first + 1] as i64 + nums[first + 2] as i64 + nums[first + 3] as i64 > target as i64 {
                break;
            }
            if target as i64 > nums[first] as i64 + nums[n - 3] as i64 + nums[n - 2] as i64 + nums[n - 1] as i64 {
                continue;
            }
            for second in first + 1..n - 2 {
                if second > first + 1 && nums[second] == nums[second - 1] {
                    continue;
                }
                if nums[first] as i64 + nums[second] as i64 + nums[second + 1] as i64 + nums[second + 2] as i64 > target as i64 {
                    break;
                }
                if target as i64 > nums[first] as i64 + nums[second] as i64 + nums[n - 2] as i64 + nums[n - 1] as i64 {
                    continue;
                }
                let mut fourth = n - 1;
                let t = target as i64 - nums[first] as i64 - nums[second] as i64;
                for third in second + 1..n - 1 {
                    if third > second + 1 && nums[third] == nums[third - 1] {
                        continue;
                    }
                    while third < fourth && nums[third] as i64 + nums[fourth] as i64 > t {
                        fourth -= 1;
                    }
                    if third == fourth {
                        break;
                    }
                    if nums[third] as i64 + nums[fourth] as i64 == t {
                        ans.push(vec![nums[first], nums[second], nums[third], nums[fourth]]);
                    }
                }
            }
        }
        return ans;
    }
}

go

func fourSum(nums []int, target int) [][]int {
    n := len(nums)
    if n < 4 {
        return nil
    }
    sort.Ints(nums)
    var ans [][]int
    for first := 0; first < n-3; first++ {
        if first > 0 && nums[first] == nums[first-1] {
            continue
        }
        if nums[first]+nums[first+1]+nums[first+2]+nums[first+3] > target {
            break
        }
        if nums[first]+nums[n-3]+nums[n-2]+nums[n-1] < target {
            continue
        }
        for second := first + 1; second < n-2; second++ {
            if second > first+1 && nums[second] == nums[second-1] {
                continue
            }
            if nums[first]+nums[second]+nums[second+1]+nums[second+2] > target {
                break
            }
            if nums[first]+nums[second]+nums[n-2]+nums[n-1] < target {
                continue
            }

            fourth := n - 1
            t := target - nums[first] - nums[second]
            for third := second + 1; third < n-1; third++ {
                if third > second+1 && nums[third] == nums[third-1] {
                    continue
                }
                for third < fourth && nums[third]+nums[fourth] > t {
                    fourth -= 1
                }
                if third == fourth {
                    break
                }
                if nums[third]+nums[fourth] == t {
                    ans = append(ans, []int{nums[first], nums[second], nums[third], nums[fourth]})
                }
            }
        }
    }
    return ans
}

c++

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ans;
        int n = nums.size();
        if (n < 4) {
            return ans;
        }
        sort(nums.begin(), nums.end());
        for (int first = 0; first < n - 3; ++first) {
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            if ((long) nums[first] + nums[first + 1] + nums[first + 2] + nums[first + 3] > target) {
                break;
            }
            if ((long) nums[first] + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) {
                continue;
            }
            for (int second = first + 1; second < n - 2; ++second) {
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                if ((long) nums[first] + nums[second] + nums[second + 1] + nums[second + 2] > target) {
                    break;
                }
                if ((long) nums[first] + nums[second] + nums[n - 2] + nums[n - 1] < target) {
                    continue;
                }
                int fourth = n - 1;
                int t = target - nums[first] - nums[second];
                for (int third = second + 1; third < n - 1; ++third) {
                    if (third > second + 1 && nums[third] == nums[third - 1]) {
                        continue;
                    }
                    while (third < fourth && nums[third] + nums[fourth] > t) {
                        fourth -= 1;
                    }
                    if (third == fourth) {
                        break;
                    }
                    if (nums[third] + nums[fourth] == t) {
                        ans.push_back({nums[first], nums[second], nums[third], nums[fourth]});
                    }
                }
            }
        }
        return ans;
    }
};

java

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> ans = new ArrayList<>();
        int                 n   = nums.length;
        if (n < 4) {
            return ans;
        }
        Arrays.sort(nums);
        for (int first = 0; first < n - 3; ++first) {
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            if ((long) nums[first] + nums[first + 1] + nums[first + 2] + nums[first + 3] > target) {
                break;
            }
            if ((long) nums[first] + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) {
                continue;
            }
            for (int second = first + 1; second < n - 2; ++second) {
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                if ((long) nums[first] + nums[second] + nums[second + 1] + nums[second + 2] > target) {
                    break;
                }
                if ((long) nums[first] + nums[second] + nums[n - 2] + nums[n - 1] < target) {
                    continue;
                }
                int fourth = n - 1;
                int t      = target - nums[first] - nums[second];
                for (int third = second + 1; third < n - 1; ++third) {
                    if (third > second + 1 && nums[third] == nums[third - 1]) {
                        continue;
                    }
                    while (third < fourth && nums[third] + nums[fourth] > t) {
                        fourth -= 1;
                    }
                    if (third == fourth) {
                        break;
                    }
                    if (nums[third] + nums[fourth] == t) {
                        ans.add(Arrays.asList(nums[first], nums[second], nums[third], nums[fourth]));
                    }
                }
            }
        }
        return ans;
    }
}

python

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        ans = list()
        n = len(nums)
        if n < 4:
            return ans
        nums.sort()
        for first in range(n - 3):
            if first > 0 and nums[first] == nums[first - 1]:
                continue
            if nums[first] + nums[first + 1] + nums[first + 2] + nums[first + 3] > target:
                break
            if nums[first] + nums[n - 3] + nums[n - 2] + nums[n - 1] < target:
                continue
            for second in range(first + 1, n - 2):
                if second > first + 1 and nums[second] == nums[second - 1]:
                    continue
                if nums[first] + nums[second] + nums[second + 1] + nums[second + 2] > target:
                    break
                if nums[first] + nums[second] + nums[n - 2] + nums[n - 1] < target:
                    continue
                fourth = n - 1
                t = target - nums[first] - nums[second]
                for third in range(second + 1, n - 1):
                    if third > second + 1 and nums[third] == nums[third - 1]:
                        continue
                    while third < fourth and nums[third] + nums[fourth] > t:
                        fourth -= 1
                    if third == fourth:
                        break
                    if nums[third] + nums[fourth] == t:
                        ans.append([nums[first], nums[second], nums[third], nums[fourth]])
        return ans


非常感谢你阅读本文~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://juejin.cn/user/2771185768884824/posts 博客原创~


开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情