题目分析
题目要求在整数数组 nums 中找出所有不重复的三元组 [nums[i], nums[j], nums[k]],使得 nums[i] + nums[j] + nums[k] == 0,同时满足 i != j != k。关键点在于如何有效地找出所有满足条件的三元组,同时避免产生重复的三元组。
解题思路
-
排序: 首先对数组进行排序,这样可以使相同的数字聚集在一起,便于后续去重。
-
递归分解: 将三数之和的问题分解为多个两数之和的问题。我们使用一个递归函数
nSum,在每一层递归中解决一个数之和的问题,直到降解到两数之和。 -
两数之和: 使用双指针方法解决两数之和的问题,通过移动指针来寻找和为目标值的数对。
-
去重: 在每一层递归中,以及在解决两数之和问题时,都需要注意去重。
代码解释
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort() # 对数组排序
return self.nSum(nums, 3, 0, 0) # 调用递归函数
def nSum(self, nums: List[int], n: int, start: int, target: int) -> List[List[int]]:
length = len(nums)
res = []
if n < 2 or length < n:
return res
if n == 2: # 当问题降解到两数之和
l, r = start, length - 1
while l < r:
s = nums[l] + nums[r]
left, right = nums[l], nums[r]
if s < target: # 移动左指针
while l < r and nums[l] == left:
l += 1
elif s > target: # 移动右指针
while l < r and nums[r] == right:
r -= 1
else: # 找到目标组合,去重并记录
res.append([left, right])
while l < r and nums[l] == left:
l += 1
while l < r and nums[r] == right:
r -= 1
else: # 当处理更多数之和问题
i = start
while i < length: # 遍历并去重
sub = self.nSum(nums, n - 1, i + 1, target - nums[i])
for arr in sub:
arr.append(nums[i])
res.append(arr)
while i < length - 1 and nums[i] == nums[i + 1]:
i += 1
i += 1
return res
在初次尝试时,选择了 for 循环来遍历数组。然而,当需要在循环中调整迭代器(例如跳过重复元素)时,for 循环由于其自动递增的特性,会导致跳过某些未处理的元素。 使用 while 循环可以更精确地控制迭代过程。当使用 while 循环时,可以在发现重复元素时手动控制迭代器的增加,从而确保每个元素都被恰当地处理。
时间复杂度和空间复杂度分析
-
时间复杂度:
- 排序的时间复杂度为 (O(N \log N))。
nSum函数中,对于每个元素,我们都在剩余元素上进行一次两数之和的操作,其时间复杂度为 (O(N))。由于nSum是递归的,总的时间复杂度为 (O(N^2))。
-
空间复杂度:
- 主要空间消耗来自排序算法,通常为 (O(\log N))。
- 递归栈的空间复杂度取决于递归的深度,这里为 (O(N))。
总的来说,这个算法的时间复杂度主要为 (O(N^2)),空间复杂度为 (O(N))。

京公网安备 11010502036488号