python刷题--N数之和问题(双指针+剪枝)
作者:互联网
1.两数之和(双指针)
这题前面已经做过,当时是用哈希表做的,时间复杂度为N
但如果换一种思路,用今天学的双指针来做,虽然在时间复杂度上不降反增(因为排序的复杂度为NlogN)但理解起来十分简单清晰。(注:对于三数四数N数之和问题来说,双指针算法相当于将最内部的两层循环优化成一层。)
思路:即先排序,得到一个有序的列表,一个指针指向列表开头,一个指向末尾,对于每一个状态而言,如果大于目标值则让右指针左移,小于目标值则让左指针右移。该方法适用于求无重复的解。
个人题解:
# 注释1
class Solution:
def twoSum(self, nums: List[int], target: int):
res = []
i, j = 0, len(nums)-1
nums.sort()
for i in range(len(nums)):
if i > 0 and nums[i-1] == nums[i]:
continue
while i < j and nums[i] + nums[j] > target:
j -= 1
if i == j: # 注释2,3
break
if nums[i] + nums[j] == target:
res.append([nums[i], nums[j]])
return res
注释1:# 注意这不是题目:两数之和的解,这代码的条件是跟后面的三数之和四数之和相同时才能成立(必须要求只返回目标值而不是返回索引)
注释2:# 能导致i=j的只有两种情况。一:由内层循环得到,那么当前状态的前一个状态nums[i]+nums[j] 是大于target的,此时期待减少两个数的和,但是控制减小的指针j已经无法向左移,所以循环结束二:由外层循环得到,那么当前状态的前一个状态nums[i]+nums[j]是小于target的,此时期待增大两个数的和,但是控制增大的指针i已经无法向右移,循环结束
注释3:在上述情况发生时(期待增大的两个数之和,但是控制增大的指针i无法向右移)。那么可不可以让j往右移动(回头)呢?
答:是不行的。看上去j向右移动,和这个状态的i是一组全新的i,j组合,是没有遍历过的,那为什么不能这样呢?
我们来假设这样的情况成立。。假设在移动之前i和j的位置分别为i0和j0那么j0向右移动后移到某个j1的位置,此时nums[i0]+nums[j1]的值是大于等于0(或者目标值的),假设i在最开始的位置是i1,那么当j第一次运动到j1的位置时,i在i1的位置,这个时候的nums[i1]+nums[j1]是小于nums[i0]+nums[j1]的,而j1运动到j0是为了使整体值减小,那么第一次的nums[i1]+nums[j1]一定就是大于0,所以对比两个状态,i1和j1这个状态下已经大于0,那么就不会再让i1增大得到i0,所以与我们一开始设定好的值大就减小,值小就增大的思想不符,假设不成立。
2.三数之和
题目:https://leetcode-cn.com/problems/3sum/
官方题解:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n = len(nums)
nums.sort()
ans = list()
# 枚举 a
for first in range(n):
# 需要和上一次枚举的数不相同
if first > 0 and nums[first] == nums[first - 1]:
continue
# c 对应的指针初始指向数组的最右端
third = n - 1
target = -nums[first]
# 枚举 b
for second in range(first + 1, n):
# 需要和上一次枚举的数不相同
if second > first + 1 and nums[second] == nums[second - 1]:
continue
# 需要保证 b 的指针在 c 的指针的左侧
while second < third and nums[second] + nums[third] > target:
third -= 1
# 如果指针重合,随着 b 后续的增加
# 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if second == third:
break
if nums[second] + nums[third] == target:
ans.append([nums[first], nums[second], nums[third]])
return ans
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/3sum/solution/san-shu-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
思想一样,就是在外层再套一个循环。
3.四数之和
题目:https://leetcode-cn.com/problems/4sum/
整体思路一样,题解可以看看,多了个剪枝操作(通过判断情况筛选掉不必要的循环)
官方题解:
4.N数之和
道理一样,就是在外层套循环。然后将最内的两层循环改为双指针操作。
标签:剪枝,target,nums,python,j1,--,second,first,指针 来源: https://blog.csdn.net/kuabiku/article/details/122777071