python
1.a+b+c=0,自由度为2,所以可以不用三循环,而使用双循环;
2.先给数组从小到大排序,即保证a≤b≤c,从而避免答案出现[a,b,c],[b,c,a]…等重复数组;
3.固定a后,寻找b,c的过程可以利用双指针,b和c分别从前往后和从后往前枚举,从而避免重复查找。
灵感:当出现互为限制的两个变量(即自由度为1)的查找问题时,可以考虑利用双指针。
class Solution:
def threeSum(self, nums):
n = len(nums)
nums.sort() # 为避免重复输出,从小到大对输入数组排序
ans = list()
for first in range(n): # a指针,从前往后
if first > 0 and nums[first] == nums[first-1]:
# 避免本次枚举数字的上次一样,从而避免重复
continue
third = n-1 # c指针从后往前,从而将三个循环减少为两个
target = 0 - nums[first]
for second in range(first+1,n): # b指针,从前往后
if second > first+1 and nums[second] == nums[second-1]:
# 避免本次枚举数字的上次一样,从而避免重复
continue
while second < third and nums[second] + nums[third] > target:
# b指针要在c指针左侧,避免重复查找
''' 由于nums排序为从小到大,故 nums[second] + nums[third] > target
可以判断b,c是否符合条件 '''
third -= 1
if second == third:
break # 第二个循环停止
if nums[second] + nums[third] == target:
ans.append([nums[first], nums[second], nums[third]])
return ans
复杂度分析:
- 时间复杂度:O(N2),其中 N是数组nums 的长度。
- 空间复杂度:O(logN),我们忽略存储答案的空间,额外的排序的空间复杂度为O(logN)。然而我们修改了输入的数组nums,在实际情况下不一定允许,因此也可以看成使用了一个额外的数组存储了nums 的副本并进行排序,空间复杂度为 O(N)。