题目描述
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]]
such that i != j
, i != k
, and j != k
, and nums[i] + nums[j] + nums[k] == 0
.
Notice that the solution set must not contain duplicate triplets.
Example 1:
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation:
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.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.
Example 2:
Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.
Example 3:
Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.
思路
本题与两数之和非常像,区别在于这次不是找两个下标不同的元素使其和为 0 ,而是要找三个下标不同的元素。既然这样,我们也可以借鉴 two sum 的思路,即:每次固定一个数组元素 nums[i]
,在剩下的数组中找两数之和,使其和为 target - nums[i]
即可。为此,我们需要一个 helper function,它的作用就是求这样的两数之和。
题目中还有一些需要注意的地方是,由于初始数组是无序且包含重复元素的,因此我们要先将原数组排序,并且在进行遍历 or 更新指针的过程中要去重。
代码参考
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res = []
i = 0
while i < len(nums):
if nums[i] > 0:
break
tuples = self.twoSumTarget(nums, i + 1, -nums[i])
for j, k in tuples:
res.append([nums[i], nums[j], nums[k]])
while i < len(nums) - 1 and nums[i] == nums[i + 1]:
i += 1
i += 1
return res
# 注意:调用这个函数之前一定要先给 nums 排序
def twoSumTarget(self, nums: List[int], start: int, target: int) -> List[List[int]]:
sz = len(nums)
res = []
# 双指针那一套操作
lo, hi = start, sz - 1
while lo < hi:
s = nums[lo] + nums[hi]
left, right = nums[lo], nums[hi]
if s < target:
while lo < hi and nums[lo] == left:
lo += 1
elif s > target:
while lo < hi and nums[hi] == right:
hi -= 1
else:
res.append([lo, hi])
while lo < hi and nums[lo] == left:
lo += 1
while lo < hi and nums[hi] == right:
hi -= 1
return res
网友评论