终极指南:如何突破百度网盘速度限制获取真实下载地址
2026/5/27 2:30:01
LeetCode 454 是一道非常典型的“用空间换时间”的题。
如果你第一次看这道题,很容易写出一个四重循环,然后立刻发现:
完了,直接超时。
但这题真正考的不是暴力,而是你能不能意识到一件事:
四个数的和为 0,其实可以拆成两部分的和互相抵消。
一旦你从A + B + C + D = 0转成(A + B) = -(C + D)
这道题的复杂度立刻从“不可做”变成了“非常稳”。
题目给了你四个长度相同的整数数组:
nums1nums2nums3nums4要求你统计有多少个四元组(i, j, k, l),满足:
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0n <= 200[-2^28, 2^28]这意味着什么?
O(n^4),最大是200^4,根本跑不完O(n^2)级别把四个数组拆成两组:
nums1+nums2nums3+nums4目标条件:
a + b + c + d = 0等价于:
(a + b) = -(c + d)nums1和nums2的所有和,记录每个和出现的次数nums3和nums4的所有和(c + d),查表看有没有-(c + d)这一步的本质是:
把四数问题,降维成两个“两数之和”的问题。
classSolution{funcfourSumCount(_nums1:[Int],_nums2:[Int],_nums3:[Int],_nums4:[Int])->Int{varsumMap:[Int:Int]=[:]// 1. 统计 nums1 + nums2 的所有可能和forainnums1{forbinnums2{letsum=a+b sumMap[sum,default:0]+=1}}varresult=0// 2. 枚举 nums3 + nums4,寻找补数forcinnums3{fordinnums4{lettarget=-(c+d)ifletcount=sumMap[target]{result+=count}}}returnresult}}varsumMap:[Int:Int]=[:]这里的字 considered 是:
nums1[i] + nums2[j]因为:
forainnums1{forbinnums2{letsum=a+b sumMap[sum,default:0]+=1}}这一段做的事情很单纯:
(i, j)a + b当成一个“中间结果”缓存起来这一步的复杂度是:
O(n²)lettarget=-(c+d)ifletcount=sumMap[target]{result+=count}这里非常关键的一点是:
+1+count原因是:
(a, b)对应同一个sum(c, d)组成一个合法四元组因为:
(a, b)只在第一阶段统计(c, d)只在第二阶段枚举letsolution=Solution()letnums1=[1,2]letnums2=[-2,-1]letnums3=[-1,2]letnums4=[0,2]print(solution.fourSumCount(nums1,nums2,nums3,nums4))输出:
2print(solution.fourSumCount([0],[0],[0],[0]))输出:
1print(solution.fourSumCount([1,-1],[-1,1],[0],[0]))逻辑上:
(1 + -1) + (0 + 0) = 0 (-1 + 1) + (0 + 0) = 0输出:
2这道题的思想在真实业务里非常常见。
比如:
你想统计:
满足某个组合约束的用户数量
直接全量组合几乎一定炸。
这是很多高性能系统的基本套路。
这道题非常适合用来区分:
O(n²)O(n²)总时间复杂度:
O(n²)n²个键值对空间复杂度:
O(n²)LeetCode 454 的关键不在代码有多复杂,而在于你是否能意识到:
如果你在刷题或写博客时,能把这道题讲清楚,基本就已经说明:
你不只是“会写题解”,而是真的理解了算法设计背后的思维方式。