跳过正文
  1. leetcode 题解/

18_四数之和

·295 字·2 分钟

类型:数组

    1. 四数之和 💛

    https://leetcode-cn.com/problems/4sum/

    ❓ 找出数组 nums 中所有满足 a + b + c + d = target 的四元组。

    💡 排序 + 双指针

    使用两重循环分别枚举前两个数,然后在两重循环枚举到的数之后使用双指针枚举剩下的两个数。

    同时可以进行如下剪枝操作:

    • 在确定第一个数之后,如果 nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target,说明此时剩下的三个数无论取什么值,四数之和一定大于 \textit{target}target,因此退出第一重循环。
    • 在确定第一个数之后,如果 nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target,说明此时剩下的三个数无论取什么值,四数之和一定小于 target,因此第一重循环直接进入下一轮,枚举 nums[i+1]
    • 在确定前两个数之后,如果 nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target,说明此时剩下的两个数无论取什么值,四数之和一定大于 target,因此退出第二重循环。
    • 在确定前两个数之后,如果 nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target,说明此时剩下的两个数无论取什么值,四数之和一定小于 target,因此第二重循环直接进入下一轮,枚举 nums[j+1]
    class Solution:
        def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
            quadruplets = list()
            if not nums or len(nums) < 4:
                return quadruplets
    
            nums.sort()
            length = len(nums)
            for i in range(length - 3):
                if i > 0 and nums[i] == nums[i - 1]:
                    continue
                if nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target:
                    break
                if nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target:
                    continue
                for j in range(i + 1, length - 2):
                    if j > i + 1 and nums[j] == nums[j - 1]:
                        continue
                    if nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target:
                        break
                    if nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target:
                        continue
                    left, right = j + 1, length - 1
                    while left < right:
                        total = nums[i] + nums[j] + nums[left] + nums[right]
                        if total == target:
                            quadruplets.append([nums[i], nums[j], nums[left], nums[right]])
                            while left < right and nums[left] == nums[left + 1]:
                                left += 1
                            left += 1
                            while left < right and nums[right] == nums[right - 1]:
                                right -= 1
                            right -= 1
                        elif total < target:
                            left += 1
                        else:
                            right -= 1
    
            return quadruplets

    时间复杂度:O(N^3),空间复杂度:O(logN)