问题描述
给你一个整数数组 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
思路分析
- 首先对数组进行排序,将数组从小到大排序,以便后续操作。
- 初始化一个空列表 res,用于存储符合条件的三元组结果。
- 开始遍历数组,以每个元素 nums[i] 作为基准。
- 在每次遍历中,使用两个指针 left 和 right 分别指向当前元素 nums[i] 的下一个元素和数组的最后一个元素。
- 在 left < right 的条件下,进行循环:
- 计算三个数的和 total = nums[i] + nums[left] + nums[right]。
- 如果 total 等于 0,说明找到了满足条件的三元组,将其加入结果列表 res 中。
- 进一步避免重复计算:如果左指针所指的元素与下一个元素相等,则将左指针右移一位,直到不相等为止;同理,如果右指针所指的元素与前一个元素相等,则将右指针左移一位,直到不相等为止。
- 将左指针右移一位,将右指针左移一位。
- 如果 total 小于 0,说明三个数之和偏小,将左指针右移一位。
- 如果 total 大于 0,说明三个数之和偏大,将右指针左移一位。
- 返回结果列表 res。
代码分析
- 将数组进行排序,以方便后续的操作。
- 初始化一个空列表 res ,用于存储结果。
- 开始遍历数组,以每个元素 nums[i] 作为基准。
- 如果当前元素与前一个元素相等,则跳过,以避免重复计算。
- 初始化指针 left = i + 1 和 right = n - 1,其中 n 是数组的长度。
- 在 left < right 的条件下,进行循环:
- 计算三个数的和 total = nums[i] + nums[left] + nums[right]。
- 如果 total 等于 0,说明找到了满足条件的三元组,将其加入结果列表 res 中。
- 进一步避免重复计算:如果左指针所指的元素与下一个元素相等,则将左指针右移一位,直到不相等为止;
- 同理,如果右指针所指的元素与前一个元素相等,则将右指针左移一位,直到不相等为止。
- 将左指针右移一位,将右指针左移一位。
- 如果 total 小于 0,说明三个数之和偏小,将左指针右移一位。
- 如果 total 大于 0,说明三个数之和偏大,将右指针左移一位。
- 返回结果列表 res。
完整代码
class Solution(object): def threeSum(self, nums): # 对数组进行排序 nums.sort() n = len(nums) res = [] # 遍历数组,以每个元素 nums[i] 作为基准 for i in range(n): # 如果当前元素与前一个元素相等,则跳过,以避免重复计算 if i > 0 and nums[i] == nums[i-1]: continue # 初始化指针 left 和 right left = i + 1 right = n - 1 # 在 left < right 的条件下,进行循环 while left < right: # 计算三个数的和 total total = nums[i] + nums[left] + nums[right] # 如果总和等于 0,说明找到了满足条件的三元组 if total == 0: # 将三元组加入结果列表 res res.append([nums[i], nums[left], nums[right]]) # 进一步避免重复计算:将左指针右移一位,直到不与下一个元素相等 while left < right and nums[left] == nums[left+1]: left += 1 # 进一步避免重复计算:将右指针左移一位,直到不与前一个元素相等 while left < right and nums[right] == nums[right-1]: right -= 1 # 将左指针右移一位,将右指针左移一位 left += 1 right -= 1 # 如果总和小于 0,将左指针右移一位 elif total < 0: left += 1 # 如果总和大于 0,将右指针左移一位 else: right -= 1 # 返回结果列表 res return res
详细分析
nums.sort()
:对输入的数组nums
进行原地排序,使其按照升序排列。n = len(nums)
:获取数组nums
的长度,即元素个数。res = []
:创建一个空列表res
,用于存储符合条件的三元组结果。for i in range(n):
:遍历数组nums
,以每个元素nums[i]
作为基准。if i > 0 and nums[i] == nums[i-1]: continue
:如果当前元素与前一个元素相等,则跳过循环,以避免重复计算。left = i + 1
:初始化指针left
,指向当前元素的下一个位置。right = n - 1
:初始化指针right
,指向数组的最后一个元素。while left < right:
:在left < right
的条件下,进行循环。total = nums[i] + nums[left] + nums[right]
:计算三个数的和total
。if total == 0:
:如果总和等于 0,说明找到了满足条件的三元组。
- 将三元组
[nums[i], nums[left], nums[right]]
加入结果列表res
。 - 进一步避免重复计算:将左指针右移一位,直到不与下一个元素相等。
- 进一步避免重复计算:将右指针左移一位,直到不与前一个元素相等。
- 将左指针右移一位,将右指针左移一位。
elif total < 0:
:如果总和小于 0,将左指针右移一位。else:
:如果总和大于 0,将右指针左移一位。return res
:返回结果列表res
。
运行效果截图
调用示例
solution = Solution() nums = [-1,0,1,2,-1,-4] nums1 = [0,1,1] print(solution.threeSum(nums)) print(solution.threeSum(nums1))
运行结果
完结