
本文深入探讨leetcode三数之和问题,分析常见超时解法的性能瓶颈,并详细介绍如何通过排序和双指针技术构建一个时间复杂度更优的解决方案。文章将提供清晰的代码示例,并解析其时间复杂度,帮助读者掌握高效处理数组求和问题的技巧,尤其是在避免重复结果方面的策略。
“三数之和”问题(3Sum)要求从一个整数数组 nums 中找出所有唯一的三元组 [nums[i], nums[j], nums[k]],使得 i != j、i != k、j != k,并且 nums[i] + nums[j] + nums[k] == 0。解决方案中不能包含重复的三元组。
原始代码尝试通过排序和嵌套的搜索函数来解决问题。虽然在小规模测试用例上可能有效,但在处理大规模或特定边缘情况时,会因为时间复杂度过高而导致“超出时间限制”(Time Limit Exceeded)。
让我们分析一下原始代码的结构和潜在的性能瓶颈:
def threeSum(nums):
sol = []
pos = 1
nums.sort() # O(N log N)
def search(p, vals): # vals 是 nums 的副本
l, r = 0, len(vals) - 1
sols = []
while l < p < r:
if vals[l] + vals[p] + vals[r] == 0:
sols.append([vals[l], vals[p], vals[r]])
# 关键问题:pop 操作
vals.pop(r) # O(N)
vals.pop(l) # O(N)
l, r = l, r - 2
p -= 1
continue
if vals[l] + vals[p] + vals[r] > 0:
r -= 1
if vals[l] + vals[p] + vals[r] < 0:
l += 1
return sols
while pos < len(nums) - 1: # 外层循环 O(N)
new_sol = search(pos, nums[:]) # 关键问题:切片操作 O(N)
for n in new_sol: # 内层循环
if n not in sol: # 关键问题:in 操作 O(K) K为sol长度
sol.append(n)
pos += 1
return sol性能瓶颈:
综合来看,这些操作导致了原始解决方案的时间复杂度远超 O(N^2),很可能达到 O(N^4) 甚至更高,因此在面对大量测试数据时会超时。
解决三数之和问题的标准高效方法是结合排序和双指针技术。这种方法能够将时间复杂度优化到 O(N^2),并且能有效处理重复三元组的问题。
from typing import List
def threeSum(nums: List[int]) -> List[List[int]]:
unique_triplets = []
nums.sort() # O(N log N)
# 遍历 i 作为第一个元素
for i in range(len(nums) - 2):
# 优化:如果当前 nums[i] 已经大于 0,则后续不可能找到和为 0 的三元组
if nums[i] > 0:
break
# 去重:跳过重复的 nums[i]
# 如果当前元素与前一个元素相同,则会产生重复的三元组,跳过
if i > 0 and nums[i] == nums[i - 1]:
continue
# 使用双指针查找剩余的两个元素
lo = i + 1
hi = len(nums) - 1
while lo < hi:
current_sum = nums[i] + nums[lo] + nums[hi]
if current_sum < 0:
lo += 1 # 和太小,增大 lo
elif current_sum > 0:
hi -= 1 # 和太大,减小 hi
else: # current_sum == 0,找到一个三元组
unique_triplets.append([nums[i], nums[lo], nums[hi]])
# 去重:跳过重复的 nums[lo] 和 nums[hi]
# 移动 lo 指针,直到它指向的元素与当前不同
while lo < hi and nums[lo] == nums[lo + 1]:
lo += 1
# 移动 hi 指针,直到它指向的元素与当前不同
while lo < hi and nums[hi] == nums[hi - 1]:
hi -= 1
# 正常移动指针,继续寻找下一个三元组
lo += 1
hi -= 1
return unique_triplets
原始超时解法:
优化后的双指针解法:
LeetCode 的“三数之和”问题是一个经典的算法题,它很好地展示了如何通过结合排序和双指针技术来优化解决方案。从一个直观但低效的暴力(或接近暴力)解法,通过识别并消除昂贵的操作(如列表切片、pop 移除和 in 查重),可以将其时间复杂度从 O(N^4) 甚至更高降低到高效的 O(N^2)。理解并掌握这种模式对于解决其他类似的数组求和问题(如两数之和、四数之和)至关重要。
以上就是优化LeetCode三数之和问题:从超时到高效的两指针解法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号