2025-2-23-4.8 回溯(基础题-组合型与排列型)

4.8 回溯(基础题-组合型与排列型)

  回溯的升级版。选择 枚举选与不选 上需要用不少心。

组合型

77. 组合

题目链接
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:
输入:n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

示例 2:
输入:n = 1, k = 1
输出:[[1]]

提示:

  • 1 <= n <= 20
  • 1 <= k <= n
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        """
        倒着来有两个优点:(1)快;(2)剪枝的条件好列出来。

        时间复杂度:分析回溯问题的时间复杂度,有一个通用公式:
                    路径长度×搜索树的叶子数。对于本题,它等于O(k⋅C(n,k))。
        空间复杂度:O(k)。
        """

        ans = []
        path = []

        def dfs(i : int) -> None:

            if k == len(path):
                ans.append(path.copy())
                return 
            
            for j in range(i,n+1):
                path.append(j)
                dfs(j + 1)
                path.pop()
        
        dfs(1)
        return ans

216. 组合总和 III

题目链接
找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

  • 只使用数字1到9
  • 每个数字 最多使用一次
    返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。

示例 2:
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。

示例 3:
输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

提示:

  • 2 <= k <= 9
  • 1 <= n <= 60
class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:

        """
        时间复杂度:O(k⋅C(9,k))
            分析回溯问题的时间复杂度,有一个通用公式:
            路径长度×搜索树的叶子数。
        空间复杂度:O(k)。返回值不计入。

        """

        ans = []
        path = []

        def dfs(i: int , t: int) -> None:
            d = k - len(path) # 还要选的数目 d

            # 这个 if 条件非常有水平!
            if t < 0 or t > (i*2 - d + 1) * d // 2:
                return

            if d == 0:
                # If you don't use copty, that ans will change with path.
                ans.append(path.copy())
                return
            
            for j in range(i, d - 1, -1):
                path.append(j)
                dfs(j - 1, t - j)
                path.pop()

        dfs(9, n)

        return ans

22. 括号生成

题目链接
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:
输入:n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]

示例 2:
输入:n = 1
输出:[“()”]

提示:

  • 1 <= n <= 8
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        """
        时间复杂度:O(n*C(2n,n))
        空间复杂度:O(n)
        """

        m = n * 2
        ans = []
        path = [''] * m

        def dfs(i: int, open: int) -> None:
            if i == m:
                ans.append(''.join(path))
                return 
            
            if open < n:
                path[i] = '('
                dfs(i + 1, open + 1)
            
            if i - open < open:
                path[i] = ')'
                dfs(i + 1, open)
            
        dfs(0, 0)
        return ans

排列型

46. 全排列

题目链接
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:
输入:nums = [1]
输出:[[1]]

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        """
        时间复杂度:O(n⋅n!),其中n为nums的长度。
        时空复杂度:O(n)
        """

        n = len(nums)
        ans = []
        path = [0] * n
        on_path = [False] * n

        def dfs(i: int) -> None:
            if i == n:
                ans.append(path.copy())
                return         
            
            for j, on in enumerate(on_path):
                if not on:
                    path[i] = nums[j]
                    on_path[j] = True
                    dfs(i + 1)
                    on_path[j] = False
                
        dfs(0)
        return ans

51. N 皇后

题目链接
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

示例 1:

在这里插入图片描述

输入:n = 4
输出:[[“.Q…”,“…Q”,“Q…”,“…Q.”],[“…Q.”,“Q…”,“…Q”,“.Q…”]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:
输入:n = 1
输出:[[“Q”]]

提示:

  • 1 <= n <= 9
class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:

        """
        时间复杂度:O(n^2*n!)。
            搜索树中至多有O(n!)个叶子,
            每个叶子生成答案每次需要O(n^2 )的时间,
        空间复杂度:O(n)
        """


        ans = []
        queens = [0] * n 
        col = [False] * n 
        diag1 = [False] * (n * 2 - 1)
        diag2 = [False] * (n * 2 - 1)

        def dfs(r : int) -> None:
            if r == n:
                ans.append(
                    ['.' * c + 'Q' + '.' * 
                    (n - 1 - c) for c in queens]
                )
                return
            
            # 在 () 放皇后
            for c, ok in enumerate(col):
                if not ok and not diag1[r+c] and not diag2[r-c]:
                    queens[r] = c 
                    col[c] = diag1[r+c] = diag2[r-c] = True
                    dfs(r + 1)
                    col[c] = diag1[r+c] = diag2[r-c] = False
            
        dfs(0)
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值