代码随想录算法训练营第二十六天 | 491.递增子序列、46.全排列、47.全排列 II、332.重新安排行程、51.N皇后、37.解数独、回溯算法总结

一、491.递增子序列

题目链接:491. 非递减子序列 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——491.递增子序列
视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili

思路:不能进行排序!!!采用树层去重,收集节点结果,仅仅要求数量大于2。

树形结构:

class Solution:
    # 1. 确定递归函数的参数和返回值
    def backtracking(self, nums, path, result, startindex):
        # 2. 确定递归终止条件
        if len(path) > 1:
            result.append(path[:])

        # 3. 确定单层递归逻辑
        used = set()                                    # 用set记录用过的元素,如果后序再set中出现则不用,去重
        for i in range(startindex, len(nums)):
            # path不能为空,且nums[i]小于path中最右边元素;同时元素在之前set中没出现过
            if (path and nums[i] < path[-1]) or nums[i] in used:
                continue                                # 如果重复后面可能有元素继续使用,而不是break
            
            used.add(nums[i])                           # 记录用过的元素
            path.append(nums[i])
            self.backtracking(nums, path, result, i+1)
            path.pop()


    def findSubsequences(self, nums: List[int]) -> List[List[int]]:
        path = []
        result = []
        self.backtracking(nums, path, result, 0)
        return result

二、46.全排列

题目链接:46. 全排列 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——46.全排列
视频讲解:组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode:46.全排列_哔哩哔哩_bilibili

Note:排列强调顺序。

树形结构:

class Solution:
    # 1. 确定递归函数的参数和返回值
    # used,标记那些用过,排序要求不重复使用
    def backtracking(self, nums, path, result, used):
        # 2. 确定递归终止条件,path大小和集合大小一样时候,可以收获结果
        if len(path) == len(nums):
            result.append(path[:])
            return

        # 3. 确定单层递归逻辑
        for i in range(len(nums)):
            # 如果用了,直接跳过元素,不重复取元素,所以continue
            if used[i]:
                continue

            used[i] = True
            path.append(nums[i])
            self.backtracking(nums, path, result, used)
            path.pop()                                      # 回溯
            used[i] = False                                 # 回溯


    def permute(self, nums: List[int]) -> List[List[int]]:
        used = [False] * len(nums)
        path = []
        result = []
        self.backtracking(nums, path, result, used)
        return result

三、47.全排列 II

题目链接:47. 全排列 II - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——47.全排列 II
视频讲解:回溯算法求解全排列,如何去重?| LeetCode:47.全排列 II_哔哩哔哩_bilibili

class Solution:
    # 1. 确定递归函数的参数和返回值
    def backtracking(self, nums, path, result, used):
        # 2. 确定递归终止条件
        if len(path) == len(nums):
            result.append(path[:])
            return

        # 3. 确定单层递归逻辑
        for i in range(len(nums)):
            if used[i]:
                continue

            # 树层去重
            if i > 0 and nums[i] == nums[i - 1] and used[i - 1] == False:
                continue
            
            used[i] = True
            path.append(nums[i])
            self.backtracking(nums, path, result, used)
            path.pop()
            used[i] = False


    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        used = [False] * len(nums)
        nums.sort()
        path = []
        result = []
        self.backtracking(nums, path, result, used)
        return result

四、332.重新安排行程(可跳过)

题目链接:332. 重新安排行程 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——332.重新安排行程

五、51.N皇后(适当跳过)

题目链接:51. N 皇后 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——51.N皇后
视频讲解:这就是传说中的N皇后? 回溯算法安排!| LeetCode:51.N皇后_哔哩哔哩_bilibili

树形结构:

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        result = []  # 存储最终结果的二维字符串数组

        chessboard = ['.' * n for _ in range(n)]  # 初始化棋盘
        self.backtracking(n, 0, chessboard, result)  # 回溯求解
        return [[''.join(row) for row in solution] for solution in result]  # 返回结果集

    def backtracking(self, n: int, row: int, chessboard: List[str], result: List[List[str]]) -> None:
        if row == n:
            result.append(chessboard[:])  # 棋盘填满,将当前解加入结果集
            return

        for col in range(n):
            if self.isValid(row, col, chessboard):
                chessboard[row] = chessboard[row][:col] + 'Q' + chessboard[row][col+1:]  # 放置皇后
                self.backtracking(n, row + 1, chessboard, result)  # 递归到下一行
                chessboard[row] = chessboard[row][:col] + '.' + chessboard[row][col+1:]  # 回溯,撤销当前位置的皇后

    def isValid(self, row: int, col: int, chessboard: List[str]) -> bool:
        # 检查列
        for i in range(row):
            if chessboard[i][col] == 'Q':
                return False  # 当前列已经存在皇后,不合法

        # 检查 45 度角是否有皇后
        i, j = row - 1, col - 1
        while i >= 0 and j >= 0:
            if chessboard[i][j] == 'Q':
                return False  # 左上方向已经存在皇后,不合法
            i -= 1
            j -= 1

        # 检查 135 度角是否有皇后
        i, j = row - 1, col + 1
        while i >= 0 and j < len(chessboard):
            if chessboard[i][j] == 'Q':
                return False  # 右上方向已经存在皇后,不合法
            i -= 1
            j += 1

        return True  # 当前位置合法

六、37.解数独(适当跳过)

题目链接:37. 解数独 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——37.解数独
视频讲解:回溯算法二维递归?解数独不过如此!| LeetCode:37. 解数独_哔哩哔哩_bilibili

七、回溯算法总结

文章讲解:代码随想录 (programmercarl.com)——回溯算法总结

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲来学习算法知识,并根据讲内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和题方法。例如,在第14训练营中,讲了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值