给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
代码:
from typing import List # 导入 List 类型,用于类型注解class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:ans = [] # 初始化一个空列表,用于存储最终的三元组结果nums.sort() # 将数组排序,方便后续使用双指针法n = len(nums) # 获取数组的长度# 遍历数组,i 作为三元组的第一个数的索引# 因为需要三个数,所以 i 最多遍历到倒数第三个数(n-2)for i in range(n - 2):x = nums[i] # 当前固定的第一个数# 如果当前数 x 和前一个数相同,则跳过本次循环# 这是为了避免重复的三元组if i > 0 and x == nums[i - 1]:continue# 优化:如果当前 x 加上最小的两个数(nums[i+1] 和 nums[i+2])已经大于 0# 由于数组是排序的,后面的数只会更大,所以可以直接退出循环if x + nums[i + 1] + nums[i + 2] > 0:break# 优化:如果当前 x 加上最大的两个数(nums[n-1] 和 nums[n-2])仍然小于 0# 说明当前 x 太小,即使加上最大的两个数也无法达到 0,所以跳过当前 xif x + nums[n - 1] + nums[n - 2] < 0:continue# 定义双指针 j 和 kj = i + 1 # j 从 i 的下一个位置开始k = n - 1 # k 从数组的末尾开始# 使用双指针法查找满足条件的三元组while j < k:s = x + nums[j] + nums[k] # 计算当前三元组的和if s > 0: # 如果和大于 0,说明需要减小和,将右指针 k 向左移动k -= 1elif s < 0: # 如果和小于 0,说明需要增大和,将左指针 j 向右移动j += 1else: # 如果和等于 0,找到一个满足条件的三元组ans.append([x, nums[j], nums[k]]) # 将三元组加入结果列表j += 1 # 移动左指针k -= 1 # 移动右指针# 跳过重复的 nums[j],避免重复的三元组while j < k and nums[j] == nums[j - 1]:j += 1# 跳过重复的 nums[k],避免重复的三元组while k > j and nums[k] == nums[k + 1]:k -= 1return ans # 返回最终的三元组结果
测试结果
输入
nums =
[-1,0,1,2,-1,-4]
输出
[[-1,-1,2],[-1,0,1]]
预期结果
[[-1,-1,2],[-1,0,1]]