DFS手写排列

虽然python中有自带的排列函数,但是在某些特殊情况需要手写排列。掌握了DFS手写排列对DFS的理解有一定的帮助。

1.手写排列(非字典序输出)

这种代码比较简单易懂,但是不是按照字典序输出。

思路

拿sta作为起始数和后面每一个数交换,sta+1再与后面的每一个数交换。

例如:1 2 3 4 ,1作为sta和后面的2进行交换变成 2 1 3 4 。

然后sta移动一位,再与后面的数交换。因为第一个数改变了,所以后面的数每次改变的数都和 1 2 3 4 是不同的,也就是新的一种排列。

具体操作写一个dfs()函数每次交换完后,把传进函数里的参数+1(sta移动一位)

def dfs(sta, end):
if sta == end:
print(li[0 : end + 1])
else:
for i in range(sta, end + 1):
li[sta], li[i] = li[i], li[sta]
dfs(sta + 1, end)
li[i], li[sta] = li[sta], li[i]

我们知道每次递归都需要写一个条件来结束递归,代码中的结束条件 sta == end 就代表sta后面已经没有可交换的数了,所以输出结果。

for i in range(sta, end + 1):
li[sta], li[i] = li[i], li[sta]
dfs(sta + 1, end)
li[i], li[sta] = li[sta], li[i]

代码里的这个 for 循环中的 i 就代表sta后面需要交换的数。

交换后完成了输出还要再交换回来。

例如:1 2 3 递归第一层 for 循环 i 可以取到 0、1、2。第一层 i 是0的时候递归到第二层还是 1 2 3 (我的例子只有三个数,递归的第三层就是输出结果)第二层 for 循环的 i 可以取到 1 和 2。i 是 1的时候2是和自己交换,然后输出 1 2 3。i 是 2的时候2是和3换,输出 1 3 2。如果不换回来的话,递归第一层 i 是 1 的时候本来到第二层是 2 1 3,但由于之前没有交换回来,第一层 for 循环 i 是 0 情况的最后一个数 1 3 2 被保留了下来,所以第一层 for 循环 i 是 1 时候的第二层的数就会变成 3 1 2,以至于后面一直出错。我们需要的是每次在 1 2 3 原数中进行交换,所以输出完后要交换回来。

整体代码

代码是 1 2 3 的全排列输出:

def dfs(sta, end):
if sta == end:
print(li[0 : end + 1])
else:
for i in range(sta, end + 1):
li[sta], li[i] = li[i], li[sta]
dfs(sta + 1, end)
li[i], li[sta] = li[sta], li[i] li = [i for i in range(1, 10)]
dfs(0, 2)

2.手写排列(字典序输出)

这种代码在手写排列中用的很多,输出也是按照字典序输出的。

思路

每次选一个数锁定,锁定的数不能再选,通过循环按顺序找到没被锁定的数添加,最后输出。我们需要定义以下几个列表:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9] # 用来排列
b = [0] * 10 # 用于输出
vis = [False] * 10 # 表示锁定
n = 3 # 需要排列的个数

下面是dfs()函数的定义:

def dfs(s, t):
if s == t:
print(b[0: n])
else:
for i in range(t):
if not vis[i]:
vis[i] = True
b[s] = a[i]
dfs(s+1, t)
vis[i] = False

递归的结束条件是递归深度达到了需要排列的个数。

for 循环每次取一个数,if 语句来判断这个数是否被锁定,如果没有被锁定在 b 列表中添加这个数,递归深度+1,然后继续判断数有没有被锁定。

这个思路有点像用暴力法手写排列组合,不过暴力法是用很多个 for 循环,每一个 for 循环写循环的范围来避免重复,而DFS这种写法是用了一个 vis 列表代表锁定来避免重复。

和上面的情况一样,输出完之后,上了锁的要解锁!

因为每次 for 循环是顺序查找有无上锁,所以输出也是按照字典序输出的。

整体代码

代码是 1 2 3 的全排列按照字典序输出:

def dfs(s, t):
if s == t:
print(b[0: n])
else:
for i in range(t):
if not vis[i]:
vis[i] = True
b[s] = a[i]
dfs(s+1, t)
vis[i] = False a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [0] * 10
vis = [False] * 10
n = 3
dfs(0, n)

var code = “d29a9066-194e-4cb5-bc78-72ecaba56faf”

DFS手写排列的更多相关文章

  1. dfs手写栈模板

    在竞赛中如果系统栈很小的话,过深的递归会让栈溢出,这个时候我们就要自己手写栈,将递归转化成手工栈. 方法其实也很简单. 基本思路上,我们就是用栈不断的pop,push.但是何时push,何时pop呢? ...

  2. 【OpenCV学习笔记】之六 手写图像旋转函数---万丈高楼平地起

    话说,平凡之处显真格,这一点也没错!  比如,对旋转图像进行双线性插值,很简单吧?  可,对我,折腾了大半天,也没有达到预期效果!  尤其是三个误区让我抓瞎好久: 1,坐标旋转公式.   这东西,要用 ...

  3. 【Machine Learning in Action --2】K-近邻算法构造手写识别系统

    为了简单起见,这里构造的系统只能识别数字0到9,需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:宽高是32像素的黑白图像.尽管采用文本格式存储图像不能有效地利用内存空间,但是为了方便理 ...

  4. k-近邻算法-手写识别系统

    手写数字是32x32的黑白图像.为了能使用KNN分类器,我们需要把32x32的二进制图像转换为1x1024 1. 将图像转化为向量 from numpy import * # 导入科学计算包numpy ...

  5. MLP 之手写数字识别

    0. 前言 前面我们利用 LR 模型实现了手写数字识别,但是效果并不好(不到 93% 的正确率). LR 模型从本质上来说还只是一个线性的分类器,只不过在线性变化之后加入了非线性单调递增 sigmoi ...

  6. hihoCoder 第136周 优化延迟(二分答案+手写堆)

    题目1 : 优化延迟 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho编写了一个处理数据包的程序.程序的输入是一个包含N个数据包的序列.每个数据包根据其重要程度不同 ...

  7. densenet tensorflow 中文汉字手写识别

    densenet 中文汉字手写识别,代码如下: import tensorflow as tf import os import random import math import tensorflo ...

  8. BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset

    BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i ...

  9. 人工智能-深度学习(3)TensorFlow 实战一:手写图片识别

    http://gitbook.cn/gitchat/column/59f7e38160c9361563ebea95/topic/59f7e86d60c9361563ebeee5 wiki.jikexu ...

  10. Tensorflow之MNIST手写数字识别:分类问题(1)

    一.MNIST数据集读取 one hot 独热编码独热编码是一种稀疏向量,其中:一个向量设为1,其他元素均设为0.独热编码常用于表示拥有有限个可能值的字符串或标识符优点:   1.将离散特征的取值扩展 ...

随机推荐

  1. BOM的概述及方法

    BOM的概述: bom 称为浏览器对象模型(bowser object model),也就意味他可以获取浏览器上的所有内容以及相关的操作.BOM缺乏规范的,存在共有对象来解决这个问题,但是共有对象也存 ...

  2. 【Unity】关于VS条件编译符号

    写在前面 起因:我在回顾LuaFramework_UGUI(作者Jarjin Lee)代码时,看到了C#代码中的条件编译符号,比如下图的ASYNC_MODE.虽然字面上知道是什么意思,但我对VS的条件 ...

  3. 第七章 狄克斯特拉算法 (Dijkstra's algorithm)

    步骤 找出最便宜的节点,即可在最短时间内前往的节点 对于该节点的的邻居,检查是否有前往他们的更短路径,如果有,就更新其开销 重复这个过程,知道对图中的每个节点都这样做了 计算最终路径 条件 只适用于有 ...

  4. 5G如何加速无人快递?5G智能网关新应用

    网上购物已经是现代生活的主流消费方式之一,伴随网购的繁荣,物流快递行业也进入到一个最火热的时期.而在这之中,有限的快递配送能力和日益增长的配送需求的矛盾持续凸显,因此无人快递车一类的创新应用也应运而生 ...

  5. sql运算符优先级

    1.() 2.* / % 3.+正 -负 +  - +连接(字符串) 4.= > < >= <= <> != !> !< 5.not 6.and 7.b ...

  6. linux 打包各种后缀的命令

    01-.tar格式解包:[*******]$ tar xvf FileName.tar打包:[*******]$ tar cvf FileName.tar DirName(注:tar是打包,不是压缩! ...

  7. windows用户名是中文引起的路径问题

    修改成英文即可

  8. flutter系列之:创建一个内嵌的navigation

    目录 简介 搭建主Navigator 构建子路由 总结 简介 我们在flutter中可以使用Navigator.push或者Navigator.pushNamed方法来向Navigator中添加不同的 ...

  9. Java笔记第十二弹

    Lambda表达式的标准格式 三要素:形式参数.箭头.代码块 格式:(形式参数)->(代码块) 形式参数:如果有多个参数,参数之间用逗号隔开:如果没有参数,留空即可 ->代表指向动作 La ...

  10. Cocos 引擎生态部负责人李阳:己之所欲,可施于人,希望通过生态促进国内引擎技术发展

    前言 "小小的身体,大大的能量,这个应该是我对大表姐最直接的感觉,在她娇小的身躯里蕴含了无限的精力和潜力,很像漫威里的神奇女侠,作为一个具备冒险精神的非典型程序员,大表姐热爱的体育活动都是很 ...