力扣刷题13

第一题:四数之和

来源:https://leetcode.cn/problems/4sum/description/

题目:

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

  • 0 <= a, b, c, d < n
  • a、b、c 和 d 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

python 复制代码
from typing import List

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
            for j in range(i + 1, n - 2):
                # 去重第二个数
                if j > i + 1 and nums[j] == nums[j - 1]:
                    continue
                left = j + 1
                right = n - 1
                while left < right:
                    total = nums[i] + nums[j] + nums[left] + nums[right]
                    if total == target:
                        result.append([nums[i], nums[j], nums[left], nums[right]])
                        # 去重第三个数
                        while left < right and nums[left] == nums[left + 1]:
                            left += 1
                        # 去重第四个数
                        while left < right and nums[right] == nums[right - 1]:
                            right -= 1
                        left += 1
                        right -= 1
                    elif total < target:
                        left += 1
                    else:
                        right -= 1
        return result

这个题和前面的"三数之和"差不多,就是多了一个数字而已。

我的思路仍然是降维,将四数之和转换为两数之和。先对数组进行排序,先固定前两个数,将问题简化为在剩下的区间里找两数之和,使四数之和等于题目中所给的target,用双指针寻找后两个数,同时跳过重复元素,避免生成重复的四元组。

我用题目中所给的示例进行模拟验证:

示例:nums = 1,0,-1,0,-2,2,target = 0

步骤1:排序

原数组:1,0,-1,0,-2,2

排序后的数组:-2,-1,0,0,1,2,len(nums) = 6

步骤2:第一层循环(i从0开始)

i = 0,numsi = -2,进入第二层循环,j从j + 1开始

j = 1,numsj = -1,初始化left = 2,right = 5,nums2 = 0,nums5 = 2,进入循环;

total = numsi + numsj + numsleft + numsright = -2 - 1 + 0 + 2 = -1 < target,left += 1;

此时left = 3,numsleft = 0,进入循环

total = numsi + numsj + numsleft + numsright = - 2 - 1 + 0 + 2 = - 1 < target,left += 1;

此时left = 4,numsleft = 1,进入循环

total = numsi + numsj + numsleft + numsright = - 2 - 1 + 1 + 2 = 0 == target,加入result。

做去重检查:检查numsleft和numsleft + 1,无重复,numsright和numsright - 1,无重复;

left += 1,right -= 1,此时left = 5 > right,退出循环。

j = 2,numsj = 0

初始化left = 3,right = 5,numsleft = 0,numsright = 2,进入循环;

total = numsi + numsj + numsleft + numsright = - 2 + 0 + 0 + 2 = 0 == target,加入result;

做去重检查:检查numsleft和numsleft + 1,无重复,numsright和numsright - 1,无重复;

left += 1,right -= 1,此时left = 4,right = 4,退出循环。

j = 3,numsj = 0(此情况下也存在重复现象,可直接排除)

初始化left = 4,right = 5,numsleft = 1,numsright = 2,进入循环;

total = numsi + numsj + numsleft + numsright = - 2 + 0 + 1 + 2 = 1 > target,right -= 1;

此时right = 4,退出循环。

j = 4,numsj = 1

初始化left = 5,right = 5,退出循环;


i = 1,numsi = -1,进入第二层循环,j从j + 1开始

j = 2,numsj = 0,初始化left = 3,right = 5,numsleft = 0,numsright = 2,进入循环;

total = numsi + numsj + numsleft + numsright = - 1 + 0 + 0 + 2 = 1 > target,right -= 1;

此时right = 4,numsright = 1,进入循环

total = numsi + numsj + numsleft + numsright = - 1 + 0 + 0 + 1 == target,加入result;

做去重检查:numsleft和numsleft + 1,无重复,numsright和numsright - 1,无重复;

left += 1,right -= 1,left = 4 > right,退出循环。


i = 2,numsi = 0,进入第二层循环,j从j + 1开始

j = 3,numsj = 0,初始化left = 4,right = 5,numsleft = 1,numsright = 2,进入循环;

total = numsi + numsj + numsleft + numsright = 0 + 0 + 1 + 2 = 3 > target,right -= 1;

此时right = 4,退出循环。


最终结果:-1,0,0,1,-2,0,0,2,-2,-1,1,2,与示例一致。

记录完毕,收工。

相关推荐
Tisfy几秒前
LeetCode 0301.删除无效的括号:二进制枚举 / 回溯
算法·leetcode·字符串·题解·回溯·括号匹配·二进制枚举
Nil2088 分钟前
leetcode 322零钱兑换
算法·leetcode·职场和发展
海绵宝宝转agent13 分钟前
2026-10-9 leetcode100刷题+面经整理
笔记·算法·面试
yi01123 分钟前
DAY24: LeetCode 167:两数之和 II|从暴力枚举到左右双指针
笔记·python·算法·leetcode·二分查找·双指针
木井巳24 分钟前
【BFS 解决拓扑排序】课程表
java·算法·leetcode·广度优先·宽度优先·推荐算法·图搜索算法
Logic10137 分钟前
C语言/数据结构数位DP题解:平滑排列数字统计——区间内相邻位差不超过K的数字个数
c语言·数据结构·动态规划·时间复杂度·数位dp·算法题·前导零处理
扶风ff44 分钟前
练题簿在线免费刷题:会员线下组卷、Word 试卷与成绩导入,课堂检测更方便
java·开发语言·算法·小程序·word
yi0111 小时前
LeetCode 15:三数之和|排序 + 双指针,如何避免重复答案?
笔记·python·算法·leetcode·双指针
-dzk-1 小时前
【多维动态规划】LC 1143.最长公共子序列
算法·动态规划
C++ 老炮儿的技术栈1 小时前
char (*csConnectName)[256]; 和 char csConnectName [256] 有什么区别
java·c语言·开发语言·c++·人工智能·算法·c