三数之和
- 题目
- 题目描述
- 示例 1:
- 示例 2:
- 示例 3:
- 题目链接
- 题解
- Python 实现
- 解释
- 提交结果
题目
题目描述
给你一个整数数组 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
题目链接
三数之和
题解
要解决这个问题,可以使用双指针法来查找所有和为零的三元组。具体步骤如下:
- 排序数组:首先对数组进行排序,这样可以方便地使用双指针法。
- 固定一个数:遍历数组,固定一个数
nums[i]
。 - 使用双指针:对于固定的
nums[i]
,使用两个指针left
和right
分别指向i+1
和数组的末尾,寻找满足nums[i] + nums[left] + nums[right] == 0
的组合。 - 去重:在遍历过程中,跳过重复的元素,避免产生重复的三元组。
Python 实现
def threeSum(nums):nums.sort() # 对数组进行排序result = []n = len(nums)for i in range(n):# 如果当前数字大于0,则三数之和不可能为0,直接返回结果if nums[i] > 0:break# 跳过重复的元素if i > 0 and nums[i] == nums[i - 1]:continueleft, right = i + 1, n - 1while left < right:total = nums[i] + nums[left] + nums[right]if total < 0:left += 1 # 如果总和小于0,移动左指针elif total > 0:right -= 1 # 如果总和大于0,移动右指针else:result.append([nums[i], nums[left], nums[right]])# 跳过重复的元素while left < right and nums[left] == nums[left + 1]:left += 1while left < right and nums[right] == nums[right - 1]:right -= 1left += 1right -= 1return result
解释
-
排序数组:
nums.sort()
对数组进行排序,使得后续的双指针操作更加方便。
-
固定一个数:
- 使用
for
循环遍历数组,固定一个数nums[i]
。 - 如果
nums[i]
大于0,因为数组已经排序,所以后续的数都会大于0,不可能找到和为0的三元组,直接返回结果。 - 跳过重复的元素,避免产生重复的三元组。
- 使用
-
使用双指针:
- 初始化两个指针
left
和right
,分别指向i+1
和数组的末尾。 - 计算当前三数之和
total
。 - 如果
total
小于0,移动左指针left
。 - 如果
total
大于0,移动右指针right
。 - 如果
total
等于0,将当前三元组加入结果列表,并跳过重复的元素,避免产生重复的三元组。
- 初始化两个指针
-
返回结果:
- 返回结果列表
result
,包含所有和为0且不重复的三元组。
- 返回结果列表
通过这种方法,可以在 O(n^2) 的时间复杂度内解决问题,效率较高。