回溯算法与深度优先搜索(DFS)的使用

本文介绍了回溯算法和深度优先搜索的概念,并通过全排列问题进行实例解析。回溯算法强调在搜索过程中通过回溯找到所有解决方案,而深度优先搜索是一种遍历策略,用于在树或图中尽可能深的搜索。文章通过代码展示了如何使用Python实现全排列的回溯算法,提供了一个清晰的解题思路。
摘要由CSDN通过智能技术生成

写在前面,感谢力扣用户liweiwei1419的文章指导
回溯算法入门级详解:https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/

首先了解一下回溯算法与深度优先搜索的定义:
回溯算法

采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两种情况:
找到一个可能存在的正确的答案;
在尝试了所有可能的分步方法后宣告该问题没有答案。

深度优先搜索

算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。这个算法会 尽可能深 的搜索树的分支。当结点 v 的所在边都己被探寻过,搜索将 回溯 到发现结点 v 的那条边的起始结点。这一过程一直进行到已发现从源结点可达的所有结点为止。如果还存在未被发现的结点,则选择其中一个作为源结点并重复以上过程,整个进程反复进行直到所有结点都被访问为止

个人理解

2021/06/15 :暂无理解在这里插入图片描述

liweiwei1419理解

「回溯算法」与「深度优先遍历」都有「不撞南墙不回头」的意思。我个人的理解是:「回溯算法」强调了「深度优先遍历」思想的用途,用一个 不断变化 的变量,在尝试各种可能的过程中,搜索需要的结果。强调了 回退 操作对于搜索的合理性。而「深度优先遍历」强调一种遍历的思想,与之对应的遍历思想是「广度优先遍历」。至于广度优先遍历为什么没有成为强大的搜索算法,我们在题解后面会提

实操案例
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
示例1:

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

是否需要用到回溯算法与深度优先算法?需要考虑这个题型是否是多阶段决策问题:

  • 求解一个问题分为很多步骤(阶段)
  • 每一个步骤(阶段啊)可以由很多种选择

使用回溯算法就是要得到所有的方案,解题时可以先用画图的方式理清自己的思路和想法。
在这里插入图片描述

  • 每一个结点代表了求解全排列问题的不同阶段,这些阶段通过变量的【不同的值】体现,这些变量的不同的值,就是状态。
  • 使用深度优先遍历有【回头】的过程,在【回头】以后,状态变量需要设置成为和先前一样,需要将修改过的变量重置为修改前的样子。
  • 深度优先遍历通过【回溯】操作,实现全局使用一份状态变量的效果

设计状态变量

  • 这颗树除了根节点和叶子节点之外,其余的节点所做的事情都是一样的:在选择了一些树的前提下,在剩下的还没有选择的数中,依次选择一个数,这慢慢理解就是一个递归的结构
  • 设置递归的终止条件:一个排列中的数字选够了。因此需要一个变量index来保存当前当前程序递归到第几层了。每递归一层,排列中的数字数量都会加一
  • 标志数字数组是否已经被选择,所以需要一个布尔数组status,false代表这些数还没有被选择。当数被选择时,将数组的相应位置设置为True。

参考代码实现:

from typing import List


class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def dfs(nums, size, depth, path, used, res):
            if depth == size:
                res.append(path)
                return

            for i in range(size):
                if not used[i]:
                    used[i] = True
                    path.append(nums[i])

                    dfs(nums, size, depth + 1, path, used, res)

                    used[i] = False
                    path.pop()

        size = len(nums)
        if len(nums) == 0:
            return []

        used = [False for _ in range(size)]
        res = []
        dfs(nums, size, 0, [], used, res)
        return res


if __name__ == '__main__':
    nums = [1, 2, 3]
    solution = Solution()
    res = solution.permute(nums)
    print(res)

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值