第14天 四数之和

建议: 要比较一下,本题和 454.四数相加II 的区别,为什么 454.四数相加II 会简单很多,这个想明白了,对本题理解就深刻了。 本题 思路整体和 三数之和一样的,都是双指针,但写的时候 有很多小细节,需要注意,建议先看视频。

题目链接:https://leetcode.cn/problems/4sum/ 视频讲解:https://www.bilibili.com/video/BV1DS4y147US

一、看到题目的第一想法

这道题的核心是:在数组中找到所有不重复的四元组,使其和等于目标值 target。

  1. 暴力解法(直接排除):最直接的思路是写四层循环,遍历所有组合,但时间复杂度是 \(O(n^4)\),效率极低,数据量大时直接超时。
  2. 优化思路迁移:参考「两数之和」「三数之和」的经验,想到可以用「排序 + 双指针」的思路,把四层循环降为两层循环 + 一层双指针,整体时间复杂度降到 \(O(n^3)\)。
  3. 关键前提:排序是基础,因为排序后可以方便地跳过重复元素,同时利用双指针快速调整和的大小。
  4. 重复处理 :题目要求结果中不能有重复的四元组,所以必须在遍历 i、j、left、right 时都跳过重复元素。

二、实现过程中遇到的困难

  1. 去重逻辑的细节处理
    • 外层 i、j 的去重:一开始容易写成 nums[i] == nums[i+1] 跳过,但正确的做法是和前一个元素比较 nums[i] == nums[i-1],且 i>0 时才判断,否则会漏掉第一个元素的有效组合。
    • 内层 left、right 的去重:找到一组解后,要跳过所有相同的 nums[left] 和 nums[right],否则会生成重复的四元组,这一步很容易忘记写。
  2. 整数溢出问题 一开始很容易忽略 int 类型的溢出问题,当四个 int 相加超过 int 范围时,会导致和的计算错误,所以必须用 long 类型来存储和,比如 (long)nums[i] + nums[j] + nums[left] + nums[right]。
  3. 剪枝逻辑的设计 一开始想不到通过提前判断和的范围来剪枝:
    • 如果当前 nums[i] 加上后续三个最小的数都大于 target,可以直接 break,因为后续的数只会更大,和不可能变小。
    • 如果当前 nums[i] 加上后续三个最大的数都小于 target,可以直接 continue,跳过当前 i。剪枝能大幅减少不必要的循环,提升效率。
  4. 双指针的移动逻辑
    • 当 sum < target 时,需要 left++ 来增大和;当 sum > target 时,需要 right-- 来减小和。一开始容易搞反移动方向,导致死循环或结果错误。
    • 找到一组解后,left 和 right 都要移动,否则会陷入重复判断。
  5. 边界条件处理 数组长度小于 4 时,直接返回空结果,这一步很容易漏掉,导致后续循环出现越界错误。

三、今日收获心得

  1. N 数之和的通用模板思想 从两数之和、三数之和到四数之和,核心思路是一致的:
    • 排序 + 外层循环固定 k-2 个数,内层用双指针找剩下两个数,时间复杂度从 \(O(n^k)\) 降到 \(O(n^{k-1})\)。
    • 排序的好处:方便去重、方便双指针调整和的大小、方便剪枝优化。
  2. 去重的核心原则所有去重操作,都是为了避免生成重复的组合,本质上是跳过 "和上一次处理过的元素相同的元素",无论是外层循环还是内层双指针,都遵循这个原则。
  3. 整数溢出的避坑意识 在涉及多个整数相加的题目中,尤其是 LeetCode 的题目,一定要注意数据范围,提前用 long 类型来存储中间和,避免溢出导致的错误结果,这是很多新手容易踩的坑。
  4. 剪枝优化的重要性 合理的剪枝能大幅减少循环次数,比如这道题中提前判断 nums[i] 与后续最大 / 最小元素的和,不符合条件就直接跳过或终止循环,这是从 "能过" 到 "高效过" 的关键一步。
  5. 代码结构的模块化思维外层循环、内层循环、双指针、去重、剪枝,每个部分的逻辑都要清晰,写的时候按步骤拆解,避免把所有逻辑堆在一起,这样不仅容易出错,也不方便调试。
相关推荐
UIU1147 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场7 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi7 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David8 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院9 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng9 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
叉烧滑蛋12 小时前
B站台湾大学郭彦甫|MATLAB 学习笔记|04 变量与档案存取
数据结构
j7~12 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
傅科摆 _ py13 小时前
DP,贪心,堆和栈,二分力扣复习
开发语言·python·算法
Shaoshing14 小时前
LeetCode100 42.接雨水
java·算法·leetcode