递归算法

[转] [博客园] 迷宫生成算法x4

余生长醉 提交于 2020-03-25 22:44:20
简介 所谓迷宫生成算法,就是用以生成随机的迷宫的算法 迷宫生成算法是处于这样一个场景: 一个row行,col列的网格地图,一开始默认所有网格四周的墙是封闭的 要求在网格地图边缘,也就是网格的边上打通2面墙 所有网格都至少保证网格周围至少有一堵墙打通 所有网格都能通过打通的墙能形成一条通路 博主已实现RecursiveBacktracking(递归回溯),RecursiveSegmentation(递归分割),随机Prim算法,Kruskal+并查集四种迷宫生成算法,这篇文章主要对这四种算法进行简要的介绍 基于Unity的迷宫生成算法代码实现 Github链接 递归回溯算法 复杂度 空间:O(n),时间:O(n),n为迷宫节点数row*col 原理 以一个栈作为辅助的数据结构,用以记录打通区域的顺序,用以回溯 一开始随机在地图中选择一个区域,加入栈。 之后在之前选择的区域周围随机选择一个未打通的区域,将新选择的区域和之前选择区域的墙打通,并把新的区域的加入栈 如果四周的区域都打通,就让栈出栈,将当期所选择的区域设置栈新的栈顶,表示回退到上一个区域 之后递归的按之前的步骤选择下一个区域直到所有区域都被打通 缺点 这种算法实现思路极为简单,但通路过于明显,甚至有可能会出现上图中的迷宫,很尴!!! 递归分割算法 复杂度 递归空间复杂度:O(row * col),最好时间复杂度:O

图解汉诺塔问题( Java 递归实现)

南楼画角 提交于 2020-03-23 23:05:00
汉诺塔简介 最近在看数据结构和算法,遇到了一个非常有意思的问题——汉诺塔问题。 先看下百度百科是怎么定义汉诺塔的规则的: 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 额,好吧,好像有点啰里啰嗦的。其实一句话就是,在三个柱子之间移动盘子,一次只能移动一个,并且要保证每一步上边的盘子都要比下边的盘子小,最终实现把所有的盘子都从最左边柱子移动到最右边的柱子上。 我找了一个小游戏,可以玩一下,体验一下这个过程。相信我,你玩不过第五关的!嘿嘿,玩不过再过来看一下,我是怎么给你做游戏攻略(作弊)的。 地址: http://www.4399.com/flash/109504_1.htm 我相信,有很多童鞋在学递归的时候,都会受到这个问题的困扰。别着急,你不是一个人,我第一次看到这个也是一脸懵逼,这什么鬼啊,这么复杂。下面我通过图解的方式,演示整个移动过程,帮助你理解用递归解决这个问题的思想。 汉诺塔图解 我们一步一步从简单到复杂。为了方便,我把三个柱子从左到右分别叫 A,B,C。盘子的数字从上到下依次增大。 一个盘子 只有一个盘子的时候,就比较简单了。如图

Top K算法

我的未来我决定 提交于 2020-03-23 17:52:10
Top K算法 问题描述 : 从arr[1, n]这n个数中,找出最大的k个数,这就是经典的TopK问题。 栗子 : 从arr[1, 12]={5,3,7,1,8,2,9,4,7,2,6,6} 这n=12个数中,找出最大的k=5个。 一、排序 排序是最容易想到的方法,将n个数排序之后,取出最大的k个,即为所得。 伪代码 : sort(arr, 1, n); return arr[1, k]; 时间复杂度 :O(n*lg(n)) 分析 :明明只需要TopK,却将全局都排序了,这也是这个方法复杂度非常高的原因。那能不能不全局排序,而只局部排序呢?这就引出了第二个优化方法。 二、局部排序 不再全局排序,只对最大的k个排序。 冒泡是一个很常见的排序方法,每冒一个泡,找出最大值,冒k个泡,就得到TopK。 伪代码 : for(i=1 to k){ ​ bubble_find_max(arr,i); } return arr[1, k]; 时间复杂度 :O(n*k) 分析 :冒泡,将全局排序优化为了局部排序,非TopK的元素是不需要排序的,节省了计算资源。不少朋友会想到,需求是TopK,是不是这最大的k个元素也不需要排序呢?这就引出了第三个优化方法。 三、堆 思路 :只找到TopK,不排序TopK。 先用前k个元素生成一个小顶堆,这个小顶堆用于存储,当前最大的k个元素。 接着,从第k

java数据结构之递归算法

旧城冷巷雨未停 提交于 2020-03-22 15:11:59
概述 程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。递归有直接递归和间接递归 •直接递归:函数在执行过程中调用本身。 •间接递归:函数在执行过程中调用其它函数再经过这些函数调用本身。 •表达方式: •递归算法有四个特性: (1)必须有可最终达到的终止条件,否则程序将陷入无穷循环; (2)子问题在规模上比原问题小,或更接近终止条件; (3)子问题可通过再次递归调用求解或因满足终止条件而直接求解; (4)子问题的解应能组合为整个问题的解。 下面将从以下几个典型的例子来讲解递归算法: 汉诺塔问题 如图,汉诺塔问题是指有三根杆子A,B,C。C杆上有若干碟子,把所有碟子从A杆上移到C杆上,每次只能移动一个碟子,大的碟子不能叠在小的碟子上面。求最少要移动多少次? 当n=1时: Move 1 from A to C 当n=2时: Move 1 from A to B Move 2 from A to C Move 1 from B to C 当n=3时: Move 1 from A to C Move 2 from A to B Move 1 from C to B Move 3 from A to C Move 1 from B to A Move 2 from B to C Move 1 from A to C 源代码 static

全排列之递归与非递归算法实现总结

放肆的年华 提交于 2020-03-21 17:01:55
全排列之递归与非递归算法实现总结 递归实现 常见的是基于交换的,原理:从而可以推断,设一组数p = {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。 因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。意思即是,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列, 如果有重复数字,则第一个数每次与后面的不同数字交换; 关键代码 Void perm(list,k,m) { If(k>m) print(list) Else { For(i=k; i<=m;i++) { Swap(&list[k],&list[i]) Perm(list,k+1,m) Swap(&list[k],&list[i]) } } } 上面这种方法可以顺序打印出所有排列,但是无序的,也无法打印出第n个排列,下面这种递归实现可以升序打印出所有排列;如果要打印第n个排列,加一个计数器就可以,但需要先生成前n-1个排列,不划算; Vector result; //存放一个排列 Bool visited; //初始化为false Void perm(list,n) {  If(result.size() >= n) print

数据结构——树的相关概念

强颜欢笑 提交于 2020-03-21 12:58:05
平衡二叉树和二叉查找树 至多有两个子节点的树成为二叉树 1)平衡二叉树 1)树的左右高度差不能超过1. 2)任何往下递归的左子树和右子树,必须符合第一条性质 3)没有任何节点的空树或只有跟节点的树也是平衡二叉树 树的节点Node是key value的形式。因为key可能不连续,甚至不是整数,所以我们没办法使用数组来表示,这个时候我们就可以用二叉查找树来实现 2)二叉查找树 树如其名,二叉查找树非常擅长数据查找。 二叉查找树额外增加了如下要求:它的左子树上所有节点的值都小于它,而它的右子树上所有节点的值都大于它。 查找的过程从树的根节点开始,沿着简单的判断向下走,小于节点值的往左边走,大于节点值的往右边走,直到找到目标数据或者到达叶子节点还未找到。 通常设计Node节点来表示key value这样的数据对 二叉查找树的insert package bobo.algo; // 二分搜索树 // 由于Key需要能够进行比较,所以需要extends Comparable<Key> public class BST<Key extends Comparable<Key>, Value> { // 树中的节点为私有的类, 外界不需要了解二分搜索树节点的具体实现 private class Node { private Key key; private Value value; private

递归函数

别来无恙 提交于 2020-03-21 04:31:37
一、初始递归 递归函数:在一个函数里在调用这个函数本身。 递归的最大深度:998 正如你们刚刚看到的,递归函数如果不受到外力的阻止会一直执行下去。但是我们之前已经说过关于函数调用的问题,每一次函数调用都会产生一个属于它自己的名称空间,如果一直调用下去,就会造成名称空间占用太多内存的问题,于是python为了杜绝此类现象,强制的将递归层数控制在了 997 (只要997!你买不了吃亏,买不了上当...). 拿什么来证明这个“998理论”呢?这里我们可以做一个实验: def foo(n): print(n) n += 1 foo(n) foo(1) 由此我们可以看出,未报错之前能看到的最大数字就是998.当然了,997是python为了我们程序的内存优化所设定的一个默认值,我们当然还可以通过一些手段去修改它: import sys print(sys.setrecursionlimit(100000)) 我们可以通过这种方式来修改递归的最大深度,刚刚我们将python允许的递归深度设置为了10w,至于实际可以达到的深度就取决于计算机的性能了。不过我们还是不推荐修改这个默认的递归深度,因为如果用997层递归都没有解决的问题要么是不适合使用递归来解决要么是你代码写的太烂了~~~ 看到这里,你可能会觉得递归也并不是多么好的东西,不如while True好用呢!然而,江湖上流传这这样一句话叫做

全排列算法--递归实现(Java)

我的梦境 提交于 2020-03-20 11:06:00
求一个n阶行列式,一个比较简单的方法就是使用全排列的方法,那么简述以下全排列算法的递归实现。 首先举一个简单的例子说明算法的原理,既然是递归,首先说明一下出口条件。以[1, 2]为例 首先展示一下主要代码(完整代码在后面),然后简述   //对数组array从索引为start到最后的元素进行全排列 public void perm(int[]array,int start) { if(start==array.length) { //出口条件 for(int i=0;i<array.length;i++) { // this.result[row][i] = array[i]; System.out.print(array[i]+" "); } // System.out.print(++this.row+": "); // System.out.println("逆序数是:"+ this.against(array)); System.out.print('\n'); } else { for(int i=start;i<array.length;i++) { swap(array,start,i); //交换数组array中索引为start与i的两个元素 perm(array,start+1); swap(array,start,i); } } } 首先数组[1, 2]分析

~~函数基础(四):递归函数~~

我们两清 提交于 2020-03-17 06:58:35
进击のpython 递归函数 学过数学的可能多多少少听过“递归”这个词 那么递归函数到底是怎么个函数呢? 老样子,从需求找方法! 我想要 100/2 结果继续除2,直到结果为零,然后打印每一步的结果 怎么写呢?可以用循环!对! n = 100 while n > 0: n = int(n / 2) print(n) 要的就是这种结果!但是,总有艮的 就想用函数来解决这个问题 甚至更过分的!还不想用循环! 能做吗?于是就有大 傻子 科学家研究出另一种写法: def func(n): n = int(n/2) print(n) func(100) 这么写还懂是吧 发现,n 这个变量就变成 50 了,然后还是要执行这个函数 也就是说,我可能要多次调用这个函数! 所以,就有了接下来的想法: def func(n): n = int(n / 2) print(n) if n > 0: func(n) func(100) 成功了!那光成功不行啊,咱们得研究研究怎么做到的呢??? 有感觉出循环了吗?通过不断的自我调用,达到了目的 每一次的函数的输出都是基于上次的返回结果! 进阶 总有刁民想害朕! 这不,有人写了这个代码! def func(n): n = int(n / 2) print(n) if n > 0: func(n) print(n) func(100) 和上面的比,就多了一句话

oracle递归函数

两盒软妹~` 提交于 2020-03-17 05:39:46
oracle start with connect by 使用方法 oracle中 connect by prior 递归算法 Oracle中start with...connect by prior子句使用方法 connect by 是结构化查询中用到的,其基本的语法是: select ... from tablename start with 条件1 connect by 条件2 where 条件3; 例: select * from table start with org_id = 'HBHqfWGWPy' connect by prior org_id = parent_id; 简单说来是将一个树状结构存储在一张表里,比方一个表中存在两个字段: org_id,parent_id那么通过表示每一条记录的parent是谁,就能够形成一个树状结构。 用上述语法的查询能够取得这棵树的全部记录。 当中: 条件1 是根结点的限定语句,当然能够放宽限定条件,以取得多个根结点,实际就是多棵树。 条件2 是连接条件,当中用PRIOR表示上一条记录,比方 CONNECT BY PRIOR org_id = parent_id就是说上一条记录的org_id 是本条记录的parent_id,即本记录的父亲是上一条记录。 条件3 是过滤条件,用于对返回的全部记录进行过滤。 简介例如以下: