三数之和为0
给一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a+b+c=0?请你找出所有和为0且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例1:
输入:nums=[-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例2:
输入:nums = []
输出:[]
示例3:
输入:nums = [0]
输出:[]
from typing import List # 导入List类型,用于类型注解
import time # 导入time模块,用于控制程序运行的速度
def threeSum(nums: List[int]) -> List[List[int]]:
"""
输入一个整数数组nums,返回所有不重复的三元组,这些三元组的和为零。
"""
if len(nums) == 0: # 如果数组为空,则直接返回空列表
return []
result = [] # 初始化结果列表,用于存放找到的三元组
unique = {} # 使用字典来存储已找到的三元组,用于去重
inv = {} # 字典,用于存储数组中的每个数字及其对应的索引
left = None # 标记数组中第一个非负数的索引
right = None # 标记数组中第一个正数的索引
nums.sort() # 对数组进行排序,为后面的查找过程做准备
i = 0 # 初始化索引
print('将列表数据整理为字典数据')
while i < len(nums): # 遍历数组,将每个数字及其索引存入字典inv
if left is None and nums[i] >= 0: # 如果left尚未赋值且当前数字非负,则赋值给left
left = i
time.sleep(1) # 等待1秒
print(f'left:{left},变量赋值')
if right is None and nums[i] > 0: # 如果right尚未赋值且当前数字为正,则赋值给right
right = i
time.sleep(1) # 等待1秒
print(f'right:{right},变量赋值')
inv[nums[i]] = i # 将数字及其索引存入字典inv
i += 1 # 索引递增
print('数据转换完成---')
if left == 0: # 如果最小的数都非负,则right设为数组长度
right = len(nums)
if right is None: # 如果数组中没有正数,则直接返回空列表
return []
i = 0 # 重新初始化索引
while i < right: # 使用i遍历到right(数组中第一个正数的索引)
j = i + 1 # 使用j作为第二个数的索引,从i的下一个位置开始
while j < len(nums) and (-nums[i]) >= nums[j]: # 确保第三个数存在
last = 0 - nums[i] - nums[j] # 计算第三个数
k = inv.get(last) # 在字典inv中查找第三个数的索引
if k and k > j: # 如果找到第三个数且其索引大于j(确保不重复)
list = [nums[i], nums[j], last] # 创建一个三元组
hash = f'{list[0]}_{list[1]}_{list[2]}' # 将三元组转换为字符串,用于去重
print(hash, '处理过程-')
print(f'unique:{unique}')
if unique.get(hash) is None: # 如果该三元组尚未被记录
unique[hash] = True # 将该三元组加入字典unique,用于去重
result.append(list) # 将该三元组对应的列表加入结果result列表
j += 1 # j递增,继续查找第二个数
i += 1 # i递增,继续查找第一个数
return result # 返回结果列表
# 测试代码
nums = [-1, 0, 1, 2, -1, -4]
print(threeSum(nums))
nums = [-1, 0, 0]
print(threeSum(nums))
nums = [-1, 0, 5]
print(threeSum(nums))
nums = [-1, -3, -5]
print(threeSum(nums))
nums = [-1, 5, 3, -2, 1, 4]
print(threeSum(nums))