0
点赞
收藏
分享

微信扫一扫

【LeetCode】15. 三数之和

总结


  • 每道题虽然都有很多种做法,都适合它的做法不多。本题如果使用深搜找出答案也是可以的,但是前提是要排序后再深搜!
  • 相比深搜,本题还有另外一种解决方法:双指针,同样,这种方法也是要求数组需要是有序的。
  • 双指针,双指针!不是单指针!千万不要弄错了方向!
  • 推荐用时:30min
  • 本题错了很多遍 ┭┮﹏┭┮

1.题目

这里提供两种方法的代码。

2.思想

2.1 方法一

使用深搜找结果。但如果使用淳朴的深搜,肯定会有超时问题,因为这就像是在n个数中挑t个出来,时间复杂度是【LeetCode】15. 三数之和_双指针,反正值很大。那么有没有一种可以降低深搜复杂度的方法呢?显然是有的,主要的思想就是结合题目要求来降低复杂度。因为数据加和大小在有序序列中是有规律的,所以我们可以利用加和大小来对深搜剪枝,从而加快值差找的过程。

2.2方法二

使用双指针的做法。但是双指针需要注意是两个下标移动的过程叫双指针,如果你固定住两个指针,只移动一个值,那就是单指针了。
我两次都错在了使用单指针,而不是双指针。

错误的想法

固定住头和尾,然后再在这个剩余的区间内找到一个数,使得三数之和为0。对于​​[-4,-1,-1,0,1,2]​​这个数组,下面给出一个示例。

  • 固定住头和尾,分别令成left = 0, right = 5,它们两的和为 -4 + 2 = -2 <0 ,那说明 第三个数要大于0才能让三数之和为0。于是我们令第三个数的下标是k = right-1。往下查找,直到三数之和为0。
  • 接着就要移动left或者right了,但是该怎么移动呢?是移动left?还是right?朴素的想法是如果原来的和>0,那么就将right-=1,如果原来的和<0,就将left+=1

得到的代码如下:

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
res = []
i,j = 0,len(nums)-1

nums.sort() # 原地排序
# print(nums)
while(i<j):
temp = nums[i] + nums[j]
tmp_j = nums[j]
tmp_i = nums[i]
# print(temp)
if temp > 0: # 说明缺负数
for k in range(i+1,j):
if temp + nums[k] == 0:
res.append([nums[i],nums[k],nums[j]])
break
# 保证移动到的新位置是不重复的
while(i<j and tmp_j==nums[j]):
j -= 1

elif temp <=0 : # 说明缺正数
for k in range(i+1,j):
if temp + nums[k] == 0:
res.append([nums[i],nums[k],nums[j]])
break
while(i<j and tmp_i==nums[i]):
i+=1
return res

上面的逻辑貌似合理,但仍然有个问题!如果碰到了这个数组​​[-2,0,1,1,2]​​​,left,right到底该怎么移动?如果是先移动left,那么就会丢失​​[-2,1,1]​​ 这个解。所以上面这个代码的逻辑是错误的!

其实正确的解法是:==固定一个数,在除此数之外的区间内使用双指针找出合适的数。==这样就避免了该怎么移动指针的问题,同时也避免了查找重复!

3. 代码

下面提供一个双指针版的代码

举报

相关推荐

0 条评论