1 中文题目

给一个由 n n n 个整数组成的数组 n u m s nums nums ,和一个目标值 t a r g e t target 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 \leq a, b, c, d < n 0a,b,c,d<n
  • a 、 b 、 c a、b、c abc d d 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
  • 可以按 任意顺序 返回答案 。

示例:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

提示:

  • 1 ≤ n u m s . l e n g t h ≤ 200 1 \leq nums.length \leq 200 1nums.length200
  • − 1 0 9 ≤ n u m s [ i ] ≤ 1 0 9 -10^9 \leq nums[i] \leq 10^9 109nums[i]109
  • − 1 0 9 ≤ t a r g e t ≤ 1 0 9 -10^9 \leq target \leq 10^9 109target109

2 求解方法:双指针+两层循环

2.1 方法思路

方法核心

将数组排序后,使用两层循环固定前两个数,对剩余区间使用双指针法寻找后两个数,在每一层都采用剪枝和去重优化,避免重复计算。

实现步骤
(1)对数组进行排序
(2)第一层循环固定第一个数:

  • 去重跳过重复数字
  • 最大最小和剪枝

(3)第二层循环固定第二个数:

  • 去重跳过重复数字
  • 最大最小和剪枝

(4)使用双指针寻找后两个数:

  • 计算四数之和
  • 根据和与目标值的比较移动指针
  • 找到目标时进行去重

方法示例

输入:nums = [1,0,-1,0,-2,2], target = 0

排序后:[-2,-1,0,0,1,2]

第一轮 i = 0 (nums[i] = -2):
    j = 1 (nums[j] = -1):
        left = 2, right = 5
        sum = -2 + (-1) + 0 + 2 = -1 < 0
        left++
        ...直到找到 [-2,-1,1,2]

第二轮 i = 1 (nums[i] = -1):
    j = 2 (nums[j] = 0):
        找到 [-1,0,0,1]
    ...

最终结果:[[-2,-1,1,2], [-1,0,0,1]]

2.2 Python代码

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        # 排序,为后续双指针和剪枝做准备
        nums.sort()
        n = len(nums)
        result = []
        
        # 第一层循环,固定第一个数
        for i in range(n-3):
            # 去重:跳过相同的第一个数
            if i > 0 and nums[i] == nums[i-1]:
                continue
                
            # 剪枝1:当前最小和超过target,后面的组合更大,直接结束
            if nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target:
                break
                
            # 剪枝2:当前最大和小于target,说明需要更大的第一个数
            if nums[i] + nums[n-3] + nums[n-2] + nums[n-1] < target:
                continue
            
            # 第二层循环,固定第二个数
            for j in range(i+1, n-2):
                # 去重:跳过相同的第二个数
                if j > i+1 and nums[j] == nums[j-1]:
                    continue
                    
                # 剪枝3:当前四数最小和超过target,内层循环可以直接break
                if nums[i] + nums[j] + nums[j+1] + nums[j+2] > target:
                    break
                    
                # 剪枝4:当前四数最大和小于target,需要更大的第二个数
                if nums[i] + nums[j] + nums[n-2] + nums[n-1] < target:
                    continue
                
                # 双指针查找剩余两个数
                left, right = j + 1, n - 1
                
                while left < right:
                    # 计算当前四数之和
                    curr_sum = nums[i] + nums[j] + nums[left] + nums[right]
                    
                    if curr_sum == target:
                        # 找到符合条件的组合,加入结果集
                        result.append([nums[i], nums[j], nums[left], nums[right]])
                        
                        # 移动左指针并去重
                        left += 1
                        while left < right and nums[left] == nums[left-1]:
                            left += 1
                            
                        # 移动右指针并去重
                        right -= 1
                        while left < right and nums[right] == nums[right+1]:
                            right -= 1
                            
                    elif curr_sum < target:
                        # 和小于目标值,左指针右移
                        left += 1
                    else:
                        # 和大于目标值,右指针左移
                        right -= 1
        
        return result

2.3 复杂度分析

  • 时间复杂度: O ( n 3 ) O(n³) O(n3)
    • 排序: O ( n l o g n ) O(nlogn) O(nlogn)
    • 第一层循环: O ( n ) O(n) O(n)
    • 第二层循环: O ( n ) O(n) O(n)
    • 双指针: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)
    • 存储结果的空间:
    • 只使用常数个变量
    • 排序可以原地进行

3 题目总结

题目难度:中等
数据结构:数组
应用算法:双指针

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部