提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
N数之和
提示:类似的一些列题解法,有两数之和,三数之和,四数之和等,这一次记录的是各种适合使用指针来做题接的方法,。博主之前不死心,秉着万物皆可递归的想法,把自己搞的欲生欲四,虽然递归加DFS的方法真的很爽,但是剪枝这个方法还需要多修炼。
1.两数之和
题目描述:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:给定 nums = [2, 7, 11, 15], target = 9。因为 nums[0] + nums[1] = 2 + 7 = 9。所以返回 [0, 1]
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
l=len(nums)
if not l:
return []
nums,ind=zip(*sorted(zip(nums,list(range(l)))))
# 使用zip函数,设置辅助队列ind,队列里的值是nums对应的下标
i=0
j=l-1
while i<j:
if nums[i]+nums[j]==target:
return [ind[i],ind[j]]
elif nums[i]+nums[j]>target:
j-=1
else:
i+=1
return []
2.三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[[-1, 0, 1], [-1, -1, 2]]
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 思路解析
# 对于传入的数组 nums, 三数之和
# 1,只要数组内的数小于3 或等于0,则返回false
# 2, 对数组进行初步排序
# 3,排序后判断第一个数的大小, 是否小于0,否则后面将不会有小于0的值,则直接返回false
# 4,对于重复的数, 直接跳过
# 5,设置左指针和右指针, L = i+1, R = N-1
# 6,遍历排序后的数组,一旦找到 s = nums[i] + nums[L+1] + nums[N-1] = 0,将这和组合加入到res队列中去
# 再判断左右边界是否出现重复的情况。
# 7,最后判断 s 小于0,则值小了,左进一位,L=L+1, 若大于0 ,则是大了,右减一位
n = len(nums)
res = []
if (not nums or n<3):
return []
nums.sort()
for i in range(n):
if (nums[i]>0):
# 判断排序后的第一个数的大小,因为target是0,若都一个大于0,就不可能找到三数之和为0
return res
if (i>0 and nums[i] == nums[i-1]): #去重,为了避免出现重复的三元组。同一层下避免同一个序列出现多次
continue
L = i+1
R = n-1
while(L<R):
if(nums[i]+nums[L]+nums[R] == 0):
# 设置返回条件,一旦找到三数之和为0的情况,返回序列
res.append([nums[i],nums[L],nums[R]])
while(L<R and nums[L] == nums[L+1]):
#当重复元素出现时,跳过当前的L,指向L+1
L=L+1
while(L<R and nums[R] == nums[R-1]):
#当重复元素出现时,跳过当前的R,指向R-1
R=R-1
L= L+1
R= R-1
elif(nums[i]+nums[L]+nums[R]>0):
# 相加大于0,数大了, R-1
R=R-1
else:
# 相加小于0,数小了, L+1
L=L+1
return res
第二种解法:泛用于N数之和,使用回溯剪枝的思路。
关键点是:
- 先对nums排序;
- 递归处理时的剪枝处理(参考注释)
这种写法参考了国际站上的文章,我觉得是最好的一种解法了。
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if not nums: return []
# 先排序,关键!
nums.sort()
ans = set()
N, target = 3, 0
self._find_sum(nums, 0, N, target, [], ans)
return list(ans)
def _find_sum(self, nums, start, N, target, path, ans):
# terminator
if len(nums) < N or N < 2: return
# process
if N == 2:
# 两数求和
d = set()
for j in range(start, len(nums)):
if target - nums[j] in d:
ans.add(tuple(path + [target - nums[j], nums[j]]))
else:
d.add(nums[j])
else:
for i in range(start, len(nums)):
# 剪枝1: target比剩余数字能组成的最小值还要小 或 比能组成的最大值还要大,就可以停止循环了
if target < nums[i] * N or target > nums[-1] * N: break
# 剪枝2: 去重
if i > start and nums[i] == nums[i - 1]: continue
# drill down
self._find_sum(nums, i + 1, N - 1, target - nums[i], path + [nums[i]], ans)
return
3.四数之和
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。