《算法通关之路》学习笔记,记录一下自己的刷题过程,详细的内容请大家购买作者的书籍查阅。
力扣第46题
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
class Solution:
def permute(self, nums: list[int]) -> list[list[int]]:
res = list()
used = set()
n = len(nums)
def dfs(path: list[int]):
if len(path) == n:
res.append(path[:]) # 加入的是拷贝不是引用
return
for i in range(n):
if i not in used:
used.add(i)
path.append(nums[i])
dfs(path)
path.pop()
used.remove(i)
dfs([])
return res
nums = [1,2,3]
solu = Solution()
solu.permute(nums)
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
力扣第47题
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
class Solution:
def permuteUnique(self, nums: list[int]) -> list[list[int]]:
res = list()
used = set()
n = len(nums)
nums.sort() # 提前排序
def dfs(path: list[int]):
if len(path) == n:
res.append(path[:])
return
for i in range(n):
# 同一个位置数字不能相同,i-1 not in used 表明这个位置i-1已经待过
if i > 0 and nums[i] == nums[i-1] and i-1 not in used:
continue
if i not in used:
used.add(i)
path.append(nums[i])
dfs(path)
path.pop()
used.remove(i)
dfs([])
return res
nums = [1,1,2]
solu = Solution()
solu.permuteUnique(nums)
[[1, 1, 2], [1, 2, 1], [2, 1, 1]]
力扣第39题
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/combination-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# 无for循环写法,必须先排序
class Solution:
def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]:
res = list()
n = len(candidates)
candidates.sort()
def dfs(idx: int, cur: int, path: list[int]):
if cur == 0: # 和为target
res.append(path[:])
return
elif idx == n: # 遍历结束
return
if candidates[idx] <= cur:
path.append(candidates[idx])
dfs(idx, cur-candidates[idx], path)
path.pop()
dfs(idx+1, cur, path)
else: # 没必要继续遍历
return
dfs(0, target, list())
return res
candidates, target = [2,3,6,7], 7
solu = Solution()
solu.combinationSum(candidates, target)
[[2, 2, 3], [7]]
# for循环写法,是否排序都可
class Solution:
def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]:
res = list()
n = len(candidates)
def dfs(idx: int, cur: int, path: list[int]):
if cur == 0: # 和为target
res.append(path[:])
return
for idx in range(idx, n):
if candidates[idx] <= cur:
path.append(candidates[idx])
dfs(idx, cur-candidates[idx], path)
path.pop()
dfs(0, target, [])
return res
candidates, target = [2,3,6,7], 7
solu = Solution()
solu.combinationSum(candidates, target)
[[2, 2, 3], [7]]
力扣第40题
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# 不使用used的写法,依据i > idx来判断
class Solution:
def combinationSum2(self, candidates: list[int], target: int) -> list[list[int]]:
res = list()
n = len(candidates)
candidates.sort()
def dfs(idx: int, cur: int, path: list[int]):
if cur == 0: # 和为target
res.append(path[:])
return
for i in range(idx, n):
# for循环中去重,这里意味着舍弃了i-1所以不能再加入i
if i > idx and candidates[i] == candidates[i-1]:
continue
if candidates[i] <= cur:
path.append(candidates[i])
dfs(i+1, cur-candidates[i], path) # 每次进入下一层时不再考虑当前数字,避免多次使用
path.pop()
else:
break
dfs(0, target, list())
return res
candidates, target = [10,1,2,7,6,1,5], 8
solu = Solution()
solu.combinationSum2(candidates, target)
[[1, 1, 6], [1, 2, 5], [1, 7], [2, 6]]
# 使用used的写法
class Solution:
def combinationSum2(self, candidates: list[int], target: int) -> list[list[int]]:
res = list()
n = len(candidates)
candidates.sort()
used = set()
def dfs(idx: int, cur: int, path: list[int]):
if cur == 0: # 和为target
res.append(path[:])
return
for i in range(idx, n):
# for循环中去重,这里意味着舍弃了i-1所以不能再加入i
if i > 0 and candidates[i] == candidates[i-1] and i-1 not in used:
continue
if candidates[i] <= cur:
path.append(candidates[i])
used.add(i)
dfs(i+1, cur-candidates[i], path)
path.pop()
used.remove(i)
else:
break
dfs(0, target, list())
return res
candidates, target = [10,1,2,7,6,1,5], 8
solu = Solution()
solu.combinationSum2(candidates, target)
[[1, 1, 6], [1, 2, 5], [1, 7], [2, 6]]
力扣第78题
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
# 不使用for循环的写法
class Solution:
def subsets(self, nums: list[int]) -> list[list[int]]:
res = []
n = len(nums)
def dfs(idx: int, path: list[int]):
if idx == n:
res.append(path[:])
return
path.append(nums[idx])
dfs(idx+1, path)
path.pop()
dfs(idx+1, path)
dfs(0, list())
return res
nums = [1,2,3]
solu = Solution()
solu.subsets(nums)
[[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]
# 使用for循环的写法
class Solution:
def subsets(self, nums: list[int]) -> list[list[int]]:
res = []
n = len(nums)
def dfs(idx: int, path: list[int]):
res.append(path[:])
for i in range(idx, n):
path.append(nums[i])
dfs(i+1, path)
path.pop()
dfs(0, list())
return res
nums = [1,2,3]
solu = Solution()
solu.subsets(nums)
[[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]
力扣第90题
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subsets-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
# 不使用used的写法,依据i > idx来判断
class Solution:
def subsetsWithDup(self, nums: list[int]) -> list[list[int]]:
res = []
n = len(nums)
nums.sort()
def dfs(idx: int, path: list[int]):
res.append(path[:])
for i in range(idx, n):
if i > idx and nums[i] == nums[i-1]:
continue
path.append(nums[i])
dfs(i+1, path)
path.pop()
dfs(0, list())
return res
nums = [1,2,2]
solu = Solution()
solu.subsetsWithDup(nums)
[[], [1], [1, 2], [1, 2, 2], [2], [2, 2]]
笔记本-Github