递归算法

递归算法

末鹿安然 提交于 2020-01-31 10:20:39
核心思想: 重复将问题分解为同类的子问题而解决问题的方法,其核心思想是分治策略。 使用条件: 1.需要解决的问题可以转化为一个或多个子问题来求解,而这些子问题的求解方法与原问题完全相同,只是在数量和规模上不同。 2.递归调用的次数必须是有限的。 3.必须有结束递归的条件来终止递归。 举例( LeetCode 894 ): 满二叉树是一类二叉树,其中每个结点恰好有 0 或 2 个子结点。 返回包含 N 个结点的所有可能满二叉树的列表。 答案的每个元素都是一个可能树的根结点。 答案中每个树的每个结点都必须有 node.val=0。 你可以按任何顺序返回树的最终列表。 思路 : 构造二叉树的思路是对于二叉树的每一层来说,我们都是先初始化一个根节点, 然后分别定义它的左子树和右子树,这个过程很明显可以递归实现。 本题要求构造满二叉树,也就是每一个结点它的左节点和右节点必须同时存在 或同时不存在,假设左子树有X个节点,总节点数为N,右子树则包含N - 1 - X个 节点,X数目从 1 开始,增加到N - 1 - 1 ,共计(N - 1 ) / 2 中情况 对于每一种子情况我们采取递归求解 : 结束条件 : 当N为偶数时,无法构造二叉树,返回空数组。 当N为 1 时,树只有一个节点,为了不破坏递归,同样返回一个数组,包含这个节 点 左右子树构造采用递归的方法。 # Definition for

非递归实现广度优先遍历(BFS)

末鹿安然 提交于 2020-01-30 20:01:30
对于广度优先遍历,使用递归方式实现非常普遍,这里我们讨论一下如何使用非递归来实现 算法 1、以图的邻接矩阵为例 2、使用一个queue来保存访问顺序,每次取队首元素,如果其有邻接点,则将其所有邻接点入队,并设置visit数组为1,最后再将其出队 3、循环结束条件为:队列为空 代码实现 以下图为例 public class BfsIterateAdjacentMatrix { private static Map < Integer , String > idVertexMap = new HashMap < Integer , String > ( ) { { put ( 0 , "V0" ) ; put ( 1 , "V1" ) ; put ( 2 , "V2" ) ; put ( 3 , "V3" ) ; put ( 4 , "V4" ) ; put ( 5 , "V5" ) ; put ( 6 , "V6" ) ; put ( 7 , "V7" ) ; } } ; private static int [ ] [ ] adjacentMatrix = new int [ ] [ ] { //V0,V1,V2,V3,V4,V5,V6,V7 { 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 } , { 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 }

java中的递归

血红的双手。 提交于 2020-01-30 17:25:59
今天我们就来说说递归 白话讲:就是自己调用自己 递归:指在当前方法内调用自己的这种现象 递归的分类 递归分为两类,直接递归和间接递归 直接递归称为方法自身调用自己 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法 递归的注意事项 递归一定要有条件限定,保证递归能够停止下来,否则会发生内存溢出 在递归中虽然有限定条件,但是递归次数不能太多,否则也会发生栈内存溢出 构造方法禁止递归,为何了:因为构造方法是创建对象使用的,总不能让对象一直创建下去把。 代码演示递归 public class Demo7 { public static void main(String[] args) { digui(1); } //定义一个静态方法 private static void digui(int i){ System.out.println(i); digui(++i); } } //结果如下图所示 我们加个条件试试 public class Demo7 { public static void main(String[] args) { digui(1); } //定义一个静态方法 private static void digui(int i){ System.out.println(i); //我们来添加一个递归结束的限定条件 if(i == 5000){ return;

剑指offer思路总结

*爱你&永不变心* 提交于 2020-01-30 16:37:46
剑指offer一共66道题,涉及到的数据结构有:数组、字符串、链表、树、二叉树、栈、队列,常用的数据操作和算法有:循环、递归、回溯、查找、排序、动规、位运算。下面将分类记录我的刷题思路 链表 从尾部到头部打印链表 (三种方法:借助栈、递归、列表的首位插入) 用栈(后入先出)保存,然后弹出; 既然想到了用栈,那一定可以 通过递归来实现 。每访问到一个结点,先递归输出其后的结点,在输出该结点自身即可; 使用Java或者python语言时,有一种比较巧妙的方法就是使用 列表的插入 方法,每次插入数据,都总是插入到首位。 来源: https://www.cnblogs.com/lthuang/p/12242901.html

巧用记忆化搜索代替暴力递归(洛谷P1464题题解,Java语言描述)

强颜欢笑 提交于 2020-01-30 15:44:59
题目要求 P1464题目链接 分析 如果……你信了这题干,真的写了递归……TLE警告!!! 所以,就需要优化嘛…… [−9223372036854775808,9223372036854775807]这个范围,就是C的 longlong / Java的 long 诶,算是一种数很大但还有良心的提示吧。 这题比较适合记忆化搜索,这也是我第一次写 记忆化搜索 的题解诶,就扯一扯…… 一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,以后再次遇到这个状态的时候,就不必重新求解了。这种方法综合了搜索和动态规划两方面的优点,因而还是很有实用价值的。 对于本题的话,只要一个记忆化储存就可以避免大量运算量(大佬们都说这玩意和递推/动态规划差不多)。 主要思路就是 开一个三维数组 ,把每一个“w”函数的值储存起来,下一次就可以 直接调用 ,节省大量时间。 使用的时候还要先想,记忆化的数组要开多大。对于这个题来说,输入数据在long(Java)范围内,对于每一组a,b,c都使用一个变量来进行记忆化是不现实的。 但是,根据题意,当a<0 or b<0 or c<0时,返回值都是1,当a>20 or b>20

枚举+递归算法:计算24

Deadly 提交于 2020-01-30 03:51:00
问题描述: 给出4个小于10的正整数,可以使用+-*/()的运算将这4个数连接起来得到一个表达式。问,是否存在一种计算方式可以使表达式的结果为24。 输入: 输入多行数据,每行包括4个小于10的正整数。最后一行数据为4个0,作为数据的终止。 输出: 对于每一组数据,如果可以得到24,则输出“YES”,否则输出“NO”。 样例输入与输出: 5 5 5 1 YES 1 1 4 2 NO 0 0 0 0 问题的分析及解决: 这个问题就是我们所熟知的算24这个数学游戏。我们先跳出如果用代码实现这个问题,思考一下,当给我们4个数字时,我们是用什么方式得出是否可以计算24这个问题。大部分人所用的方法都是连拼带凑的方法得出结论的,即尝试将几个数字进行+-*/运算,拼凑出是否为24。如果将这种思想转化为算法思想,我们首先想出的便是枚举,即把数字两两计算,并且把所有的可能性都列举出来,例如:我们已知A,B,C,D这4个数字,我们先尝试A,B;A,C;A,D;B,C;B,D;C,D这6组数的+-*/,并把这6组数得出的结果与剩下的值重复进行上述的操作,直至剩余最后2个数尝试进行+-*/,看看是否能够得出24这个值,如果最终的结果为24,那么输出YES,否则输出NO。 在编写代码的过程中,我们会发现,如果用非递归的方式写代码,将会嵌套好几层for循环,且代码显得非常的冗余,所以在循环重复计算时

zkw线段树

一世执手 提交于 2020-01-29 21:09:16
zkw线段树是zkw大神搞的自底向上线段树,以常数小,代码短著称。然而zkw大神的原ppt中描述简单,想了好长时间才想粗来。 以下内容针对 区间最小值 ,使用更好理解的递归方式描述。 定义 zkw线段树定义如下: 1. 它是一棵 满二叉树 2. 他的叶节点是一个数 3. 每一个非叶节点是一个数,且这个数是它的两个孩子中的较小值 显然,zkw线段树和普通线段树类似。他的叶节点从左到右是一个数列A1..n,非叶节点存一些信息以便查询区间最小值。 由于它是一个满二叉树,可以用 堆式储存法 储存。特别的,由于叶节点的个数为2的正整数幂,对于数据规模n,叶子节点的实际个数为 2 lg n + 1 , 没有数据的节点用 ∞ 填充 。 性质 不难发现,一棵有tn个节点的满二叉树有tn-1个非叶子节点。所以在堆式结构中,第i个叶子节点的位置是 tree[tn-1+i] 。这是一个很重要的性质,zkw线段树的许多操作是建立在他的基础上的。 由1容易得出,对于树上(堆中)任意一个位置i,如果i是偶数,那么它是一个左孩子;否则是一个右孩子。 1 2 3 4 5 6 7 //显然,所有奇数都是右孩子,偶数都是左孩子 建立数据结构 直接用静态数组建立即可,i的左右孩子分别为 i*2,i*2+1 const int maxn = 100000; // 最多节点数 int tree[maxn*4]; //

二叉树的遍历.队列与栈实现

天大地大妈咪最大 提交于 2020-01-29 20:45:32
树的遍历方法有广度优先(层序遍历),以及深度优先两种方法,分成先序遍历,中序遍历,后序遍历三种。 一.深度优先: 1.递归实现: 先序遍历 输出顺序:根节点,左子树,右子树。 void PreOrderTraversal ( BinTree BT ) { if ( BT ) { //如果树非空 printf ( "%d" , BT - > Data ) ; //输出根节点 PreOrderTraversal ( BT - > Left ) ; //继续递归执行其左子树 PreOrderTraversal ( BT - > Right ) ; //继续递归其右子树 } } 中序输出:左子树,根节点,右子树。 只需要将输出语句放到两个递归语句之间即可。 void PreOrderTraversal ( BinTree BT ) { if ( BT ) { PreOrderTraversal ( BT - > Left ) ; printf ( "%d" , BT - > Data ) ; PreOrderTraversal ( BT - > Right ) ; } } 后序输出:左子树,右子树,根节点。 void PreOrderTraversal ( BinTree BT ) { if ( BT ) { PreOrderTraversal ( BT - > Left ) ;

递归与尾递归

送分小仙女□ 提交于 2020-01-29 16:34:12
1.递归 递归是一个函数直接或间接地调用自身,是为直接或间接递归。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。用递归需要注意以下两点: (1) 递归就是在过程或函数里调用自身。(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。 递归一般用于解决三类问题:   (1)数据的定义是按递归定义的。(Fibonacci函数,n的阶乘)   (2)问题解法按递归实现。(回溯)   (3)数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索) 递归的缺点:   递归解题 相对常用的算法如普通循环等,运行效率较低 。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储,因此递归次数过多容易造成 栈溢出 。 代码: int FibonacciRecursive(int n) { if( n < 2) return n; return (FibonacciRecursive(n-1)+FibonacciRecursive(n-2)); } 递归写的代码非常容易懂,完全是根据函数的条件进行选择计算机步骤。例如现在要计算n=5时的值,递归调用过程如下图所示: 2.尾递归 尾递归就是从最后开始计算,

递归算法:苹果放置问题

半腔热情 提交于 2020-01-29 12:23:55
问题描述: 把M个苹果放在N个盘子中,允许有盘子为空,共有多少种放置的方法。1.2.1和2.1.1是同样的放置方法。 输入: 第一行是测试数据的数目Num(0<=Num<=20)。以下每行均包含2个整数M和N,以空格分开。1<=M,N<=10。 输出: 对输入的每组数据M和N,用一行输出相应的K。 样例输入: 1 7 3 样例输出: 8 问题的思考及解决: 这题的思考模式和爬楼梯有点相似,也是类似于排列组合的问题,但是又不能用排列组合的思想来处理这个问题,需要用递归的思想来处理这个放置苹果的问题。 这个题目有3个需要考虑的问题点: 1)苹果和盘子数目的大小是否影响递归的思路 2)苹果和盘子如何进行递归求解摆放的数量 3)递归终止的条件 先从第一个问题考虑:当盘子数多于苹果数时,无论怎么放置,必然会有盘子多出来的。我们假设写个函数叫PlaceApple(m,n),返回值为放置的方法,那么当m<n时,有PlaceApple(m,n)=PlaceApple(m,m)。 那么如果m>n时,如何处理呢,此时我们会发现,在这种情况下,可能有盘子多出来,也可能没有盘子多出来。苹果放置的方法就为没有空盘子的情况和有空盘子的情况的总和,即为:PlaceApple(m,n)=PlaceApple(m, n - 1) + PlaceApple(m - n, n)。PlaceApple(m, n - 1