leetcode刷题笔记——回溯法

leetcode刷题笔记——回溯法

目前完成的回溯法的leetcode算法题序号:
中等:60, 93, 79
困难:

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reconstruct-itinerary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


算法理解

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

找到一个可能存在的正确的答案;
在尝试了所有可能的分步方法后宣告该问题没有答案。

做题的时候,建议 先画树形图 ,画图能帮助我们想清楚递归结构,想清楚如何剪枝。拿题目中的示例,想一想人是怎么做的,一般这样下来,这棵递归树都不难画出。

在画图的过程中思考清楚:

  1. 分支如何产生;
  2. 题目需要的解在哪里?是在叶子结点、还是在非叶子结点、还是在从跟结点到叶子结点的路径?
  3. 哪些搜索会产生不需要的解的?例如:产生重复是什么原因,如果在浅层就知道这个分支不能产生需要的结果,应该提前剪枝,剪枝的条件是什么,代码怎么写?

一、60题:排列序列

1.题干

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。

2.思路

最直接的思路是通过回溯法得到所有的排列,然后从取出对应的排列。

但是这题显然考察的是回溯法的剪枝,如何高效的剪枝才是关键。

根据题意,要寻找第k个排列,就需要考虑按照哪种排列方式下的第k种,根据例子可以看出按照大小顺序得到的排列集合,与常规的回溯法得到的集合是一样的顺序,我们就只需要考虑剪枝的问题。

这里第k个排列,可以发现,排列的第一个数有n种选择,第一个数确定之后,后续的 n − 1 n-1 n1个数有 ( n − 1 ) ! (n-1)! (n1)种组合,所以通过 k / ( n − 1 ) ! k/(n-1)! k/(n1)!就能得到目标排列的第一个数应该是哪个,后续的依次类推,要注意的是这里第k个排列,k是从1开始的,这与索引常用的0开始,要区别开来。

3.代码

import math
class Solution:
    def getPermutation(self, n: int, k: int) -> str:
        def dfs(n, level, used, path, k):
            if len(path) == n:
                return
            #m1表示这一层应该选择第几个数进入排列
            m1 = k // math
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值