LeetCode 刷题之回溯算法

柔情只为你懂 2023-09-29 19:23 75阅读 0赞

1. 回溯算法框架套路

回溯可以理解是暴力递归 + 剪枝,解决一个回溯问题,实际上就是一个决策树的遍历过程,大致需要分为以下三步

  • 路径:已作出的选择
  • 选择列表:即当前可以做的选择
  • 结束条件:即达到决策树底层,无法再做选择的条件

    result = []
    def backtrack(路径, 选择列表):

    1. if 满足结束条件:
    2. result.add(路径)
    3. return
    4. for 选择 in 选择列表:
    5. 做选择
    6. backtrack(路径, 选择列表)
    7. 撤销选择

参考:回溯算法详解(修订版)

2. 全排列

46. 全排列

  1. 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
  2. 示例 1
  3. 输入:nums = [1,2,3]
  4. 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
  5. 示例 2
  6. 输入:nums = [0,1]
  7. 输出:[[0,1],[1,0]]
  8. 示例 3
  9. 输入:nums = [1]
  10. 输出:[[1]]
  11. 提示:
  12. 1 <= nums.length <= 6
  13. -10 <= nums[i] <= 10
  14. nums 中的所有整数 互不相同

题解:

  1. class Solution:
  2. def permute(self, nums: List[int]) -> List[List[int]]:
  3. res = []
  4. track = []
  5. self.backtrack(res, track, nums)
  6. return res
  7. def backtrack(self, res, track, nums):
  8. # bad case
  9. if len(track) == len(nums):
  10. res.append(track[:])
  11. return
  12. for i in range(0, len(nums)):
  13. if nums[i] in track:
  14. continue
  15. track.append(nums[i])
  16. self.backtrack(res, track, nums)
  17. track.pop() # 撤销条件

3. 子集

78. 子集

  1. 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
  2. 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
  3. 示例 1
  4. 输入:nums = [1,2,3]
  5. 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
  6. 示例 2
  7. 输入:nums = [0]
  8. 输出:[[],[0]]
  9. 提示:
  10. 1 <= nums.length <= 10
  11. -10 <= nums[i] <= 10
  12. nums 中的所有元素 互不相同

题解:

  1. class Solution:
  2. def subsets(self, nums: List[int]) -> List[List[int]]:
  3. res = []
  4. track = []
  5. self.backtrack(res, nums, track, 0)
  6. return res
  7. def backtrack(self, res, nums, track, start):
  8. """
  9. start: 控制树枝的生长避免产生重复的子集
  10. track:记录根节点到每个节点的路径的值
  11. [] 也是它的子集
  12. """
  13. res.append(track[:])
  14. # base case
  15. if start == len(nums):
  16. return
  17. for i in range(start, len(nums)):
  18. track.append(nums[i])
  19. self.backtrack(res, nums, track, i + 1)
  20. track.pop()

参考:一文秒杀排列组合问题的 9 种题型

4. 括号生成

22. 括号生成

  1. 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
  2. 示例 1
  3. 输入:n = 3
  4. 输出:["((()))","(()())","(())()","()(())","()()()"]
  5. 示例 2
  6. 输入:n = 1
  7. 输出:["()"]
  8. 提示:
  9. 1 <= n <= 8

题解:

  1. class Solution:
  2. def generateParenthesis(self, n: int) -> List[str]:
  3. result = []
  4. self.backtracking(n, result, 0, 0, "")
  5. return result
  6. def backtracking(self, n, result, left, right, s):
  7. # 右括号数目大于左括号数目就不符合有效括号组合
  8. if right > left:
  9. return
  10. if left == n and right == n:
  11. result.append(s)
  12. return
  13. # 先加左括号
  14. if left < n:
  15. self.backtracking(n, result, left+1, right, s + "(")
  16. # 右边的括号小于左边的括号,加右边的括号
  17. if right < left:
  18. self.backtracking(n, result, left, right+1, s + ")")

发表评论

表情:
评论列表 (有 0 条评论,75人围观)

还没有评论,来说两句吧...

相关阅读

    相关 方法:回溯

    1:回溯法和动态规划的区别 共同点 用于求解多阶段决策问题。多阶段决策问题即: 求解一个问题分为很多步骤(阶段); 每一个步骤(阶段)可以有多种选择。 不