给定一个包含 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] 输出:[]
提示:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/1fGaJU
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
【python快速版】
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res = []
n = len(nums) -1
#确定第一个数,然后找后面两个数不重复之和等于 第一个数的相反数
for i in range(n-1):
if i > 0 and nums[i] == nums[i-1]:
continue
j = i +1
k = n
target = nums[i] * -1
while j < k:
su = nums[j] + nums[k]
if su > target:
k -= 1
continue
if su < target:
j += 1
continue
if su == target:
res.append([nums[i],nums[j],nums[k]])
#将和j相同元素跳过
while j<k:
#j要先后移一格,避免首次进入,匹配到i的元素
j += 1
if nums[j] != nums[j-1]: #移动到和j不同的一个元素
break
while j < k:
k -= 1
if nums[k] != nums[k+1]:
break
return res
【思想要点】
「不重复」的本质是什么?我们保持三重循环的大框架不变,只需要保证:
- 第二重循环枚举到的元素不小于当前第一重循环枚举到的元素;
- 第三重循环枚举到的元素不小于当前第二重循环枚举到的元素。
双指针常用场景:
当我们需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法,将枚举的时间复杂度从 O(N^2)减少至O(N)。
加上第一重循环,时间复杂度为 O(N),因此枚举的总时间复杂度为 O(N^2)。由于排序的时间复杂度为 O(NlogN),在渐进意义下小于前者,因此算法的总时间复杂度为 O(N^2)
空间复杂度为 O(N)