1、Leetcode15.三数之和 链接
这道题是一个典型的双指针,可能会有一个疑问,三个数,为什么会是双指针啊,最近好久没有做题了,当看到这个题的时候,我的想法也是用三个指针去遍历,但是发现其实有一个指针可以是固定的,接下来看一下这个题的答案就知道了。
思考:
看到这道题的时候,我第一个想法就是先将nums进行一个升序排序
第二个想法就是判断特例,有哪些特例呢?
1)如果nums的长度小于等于2,那么直接返回空列表
2)如果指针移动时,发现当前所指向的元素和上一个元素是一样的,那么应该跳过
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 1、特判,对于数组长度n,如果数组为null或者数组长度小于3,返回[]
# 2、对重复数组:跳过,避免出现重复解
# 令左指针L= i+1, 右指针R=n-1,当L<R时,执行循环:
# 当nums[i] +nums[L]+nums[R] == 0,执行循环,判断左界和右界是否和下一位置重复,去除重复解,并同时将L,R移到下一位置,寻找新的解
# 若和大于0,说明nums[R]太大,R左移
# 若和小于0,说明nums[L]太小,L右移
# 复杂度分析:时间复杂的 O(n^2),数组排序O(NlogN),遍历数组O(n),双指针遍历O(n),总体O(NlogN)+O(n^2)
nums.sort()
n = len(nums)
res = []
if not nums or n<3:
return res
for i in range(n):
# 如果第一个指针都大于0了,那么必不可能有三数之和为0的情况了。
if nums[i]>0:
return res
if i>=1 and nums[i]==nums[i-1]: # 当i>0,即从i=1开始就需要判断,避免出现重复解
continue
l,r = i+1,n-1
while l<r:
if nums[i]+nums[l]+nums[r]==0:
res.append(nums[i],nums[l],nums[r])
while l<r and nums[l]==nums[l+1]:
l+=1
while l<r and nums[r]==nums[r-1]:
r-=1
l+=1
r-=1
elif nums[i]+nums[l]+nums[r] >0:
r-=1
else:
l+=1
return res
2、Leetcode16.最接近的三数之和 链接
可以看到这道题可以演化成三数之和,所以说三数之和可以当作这道题的一个特例,我们完全可以用三数之和的思路解决这道题,但是我们并不需要判断左右指针已经重复问题,如果你想缩短运行时间,那么确实可以多做一些判定。
话不多说,直接上代码思路:
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
ans = sum(nums[:3]) # 这里先计算前三个元素做一个初始对比量
n = len(nums)
for i in range(n):
l,r = i+1,n-1
while l<r:
tmp = nums[i]+nums[l]+nums[r]
if tmp == target:
return tmp
elif tmp < target:
l+=1
else:
r-=1
if abs(tmp-target)<abs(ans-target):
ans = tmp
return ans