递归算法

Leetcode题目46.全排列(回溯+深度优先遍历+状态重置-中等)

回眸只為那壹抹淺笑 提交于 2019-12-03 10:27:06
题目描述: 给定一个没有重复数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 题目解析:来自leetcode@ liweiwei1419 以示例输入: [1, 2, 3] 为例,如果让我们手写,要做到不重不漏,我们书写的策略可能是这样:“一位一位确定”,这样说比较笼统,具体是这样的: 1、先写以 1 开始的两个排列:[1, 2, 3]、[1, 3, 2]; 2、再写以 2 开始的两个排列:[2, 1, 3]、[2, 3, 1]; 3、最后写以 3 开始的两个排列:[3, 1, 2]、[3, 2, 1]。 如果数组元素多一点的话,也不怕,我们写的时候遵循下面的原则即可: 1、按数组的顺序来(不要求排序,但我们选取元素的顺序是从左到右的),每次排定 1 个元素; 说明:只有按照顺序才能做到不重不漏。 2、新排定的元素一定不能在之前排定的元素中出现。 说明:如果违反了这一条,就不符合“全排列”的定义。 其实让程序帮你找到所有的全排列也是这样的思路。如果不是这样的话,我们要写数组长度这么多层的循环,编码极其困难,代码写出来也非常不好看。 这道题可以作为理解“回溯算法”的入门题。这是一个非常典型的使用 回溯算法 解决的问题。解决回溯问题,我的经验是

递归—八皇后问题

≡放荡痞女 提交于 2019-12-03 10:11:21
八皇后问题 说明:   八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即: 任意两个皇后都不能处于同一行、同一列或统一斜线上,问有多少中摆法(92) 。 思路分析: (1)第一个皇后先放第一行第一列 (2)第二个皇后放在第二行第一列、然后判断是否OK,如果不OK,继续放在第二列、第三列、依次把所有列都放完,找到一个合适 (3)当得到一个正确解时,在栈回退到上一个栈时,就会开始回溯,即将第一个皇后,放到第一列的所有正确解,全部得到。 (4)然后回头继续第一个皇后放到第二列,后面继续循环执行1,2,3,4的步骤 (5) 来源: https://www.cnblogs.com/niujifei/p/11787987.html

尾递归实现斐波那契数列

一笑奈何 提交于 2019-12-03 10:04:17
一、斐波那契数列 斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368...... 二、递归算法 1. 代码 public int fib(int n){ if(n==1 || n==2){ return 1; } return fib(n-1)+fib(n-2); } 2. 缺点:多次计算重复的fib(n),性能低,一般只用于说明递归算法 三、改进:空间换时间,把计算出来的fib(n)存储起来,不用重复计算,空间复杂度O(n) public int fib(int n){ int[] array=new int[n]; array[0]=1; array[1]=1; for(int i=2;i<n;i++){ array[i]=array[i-1]+array[i-2]; } return array[n-1]; } 四、再次改进,空间减少到O(1),只存储3个数:前两个数和前两个数相加计算出来的结果 public int fib(int n){ int first=1; int second=2; int third=3; for(int i=3;i<=n;i++){ third=first

递归

半城伤御伤魂 提交于 2019-12-03 10:03:46
一、递归   1、递归应用场景     递归的实际应用场景,迷宫问题(回溯),递归(Recursion)        2、递归的概念     简单的说: 递归就是方法自己调用自己 ,每次调用时 传入不同的变量 ,递归有助于编程者解决复杂的问题,同时,可以让代码更加简洁。   3、递归调用机制     递归调用机制,常见应用:     (1)打印问题 1 public static void test(int n) { 2 if (n > 2) { 3   test(n - 1); 4 } 5 System.out.println("n=" + n); 6 }     (2)阶乘问题 1 //阶乘 2 public static int factorial(int n) { 3 if (n == 1) { 4 return 1; 5 } else { 6 return factorial(n - 1) * n; // 1*2*3 7 } 8 } 9     图解:   4、递归能解决的问题     (1)各种数学问题如:八皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题     (2)各种算法中也会使用到递归,比如快速排序,归并排序,二分查找,分治算法等     (3)将用栈解决的问题—>递归代码比较简洁   5、递归需要遵守的重要规则     (1)执行一个方法时

算法第三章作业

随声附和 提交于 2019-12-03 09:54:21
1. 你对动态规划算法的理解 适用于解最优化的问题,像是分治法的优化与升级吧。与分治法类似,基本思想是将待解决的问题分成多个子问题,先求解子问题,再结合子问题得到原问题的解。不同的是,动态规划分解得到的子问题不是相互独立的。而且,通过一个表来记录所有已解决的子问题答案,避免了分治法中的大量重复计算。 2. 分别列出编程题1、2的递归方程 编程题1的递归方程:m[i] = max {m[k] | a[k] < a[i]} (1 <= k < i) 编程题2的递归方程:m[i] = min {c[i][k] + m[k]} (i<k<=n) (m[i]表示从i站出发到目的地的最小费用、c[i][j]表示从i站到j站的费用) 边界: m[n] = 0 3. 说明结对编程情况 在这次结对编程过程中,我发现了自身存在的问题,很多时候都是能想出解决问题的方法,能写出递归方程,却经常卡在打代码上。日后一定要加强代码这一方面。除此,结对编程通过交流提高了解题的效率,希望能够继续一起加油吧!! 来源: https://www.cnblogs.com/yjh838328354/p/11787194.html

算法第三章作业

狂风中的少年 提交于 2019-12-03 09:42:18
1.你对动态规划算法的理解。 动态规划算法可以算是分治法的优化版,其思想也是将原问题分解成若干个非独立的子问题,先得子问题的解再得原问题的解。动态规划算法适用于解最优化问题,首先找出最优解性质,递归地定义最优值,再自底向上的方式计算出最优值,最后根据最优值时得到的信息构造最优解。 2.分别列出编程题1、2的递归方程。 (1)m [ i ] = m a x { m [ k ] | a [ k ] < a [ i ] } 1 < = k < i (2)m [ i ] = m i n { c [ i ] [ k ] + m [ k ] } 3.说明结对编程的情况。 结对编程进行得比较顺利,互相学习共同进步,也多了一个可以监督自己学习的对象。 来源: https://www.cnblogs.com/chengyi1102/p/11785911.html

算法第三章作业

ε祈祈猫儿з 提交于 2019-12-03 09:33:33
1. 你对动态规划算法的理解 动态规划算法适用于解最优化问题,可以算作分治法的优化和升级。在用分治法求解问题时,有些子问题被重复计算了许多次。如果能够保存已经解决的子问题的答案,在需要时再找出已求得的答案,这样可以避免大量的重复计算,从而得到多项式时间算法。为达到此目的,可以用一个表来记录所有已解决的子问题的答案。动态规划的基本思想就是,无论子问题以后是否被用到,只要它被计算过,就将其结果存入表中。运用动态规划法的最关键步骤就是写出递归表达式。 2. 分别列出编程题1、2的递归方程 编程题1的递归方程:m[i]=1 , n=1 m[i]=max{ m[k+1] , m[i] } , (a[k]<a[i], 1<=k<i, n>1) 编程题2的递归方程:m[i]=min{ c[i][k]+m[k] }, (i<k<=n) (从i站出发到目的地的最小费用) (c[i][j]表示从i站到j站的费用) 3. 说明结对编程情况 在结对编程过程中,彼此的交流能够更有效率完成题目,也促进了双方的进步,希望在以后实践讨论的过程中收获更多知识,不断成长。 来源: https://www.cnblogs.com/Daylight-Deng/p/11785589.html

算法第三章作业

瘦欲@ 提交于 2019-12-03 09:30:18
1.动态规划是求解决策过程最优化的数学方法,也是一种能够减少重复运算的一种算法,比较适合原问题能依赖于子问题解得, 而子问题也能够依赖于子子问题解得而出的问题。 2. 编程题1和编程题2的递归方程 3-1 m[ i ] = a[ i ] i = 0; max { a[ i ] , a[ i ] + m[ i - 1 ] } i > 0 3-2 m[ i ] = min { c[ i ][ k ] + m[ k ] } (边界条件为m[ n ] = 0,n为终点) 3. 结对编程情况 结对编程一直都在进行,对自己的帮助还是很大,能知道自己的不足然后与伙伴交流,很好的提升自己的方式。 来源: https://www.cnblogs.com/fengwanthousand/p/11785477.html

算法第三章作业

天涯浪子 提交于 2019-12-03 08:18:17
1. 你对动态规划算法的理解 动态规划的实质是分治思想和解决冗余,他与贪心和分治法类似,它们都将问题分为更小的类似的子问题。但贪心算法可能不能得到全局最优解,动态规划可以处理不具有贪心实质的问题。 2. 分别列出编程题1、2的递归方程 (1. f[i] = max{ f[k] | a[k] < a[i] } (1<=k<i) (2. f[i] = min{ f[k] + a[i][k] } (i<k<=j) 3. 说明结对编程情况 我和队友会先自己思索一段时间,其中一人敲另一个看,其间会有相互提问交流。 来源: https://www.cnblogs.com/qq2766022474/p/11784756.html

算法第三章作业

旧街凉风 提交于 2019-12-03 07:49:24
1.对动态规划算法的理解 1)动态规划算法是一种用于求解具有最优解性质问题的算法。2)与递归方法比,动态规划算法用来解决子问题被重复计算多次的情况且没有栈溢出的风险。3)递归方法、递归备忘录方法都是自顶向下的算法,而动态规划算法是自顶向下的迭代算法,避免了子问题的重复计算。4)动态规划通常可以把时间复杂度从指数级降到多项式级。5)动态规划算法是用空间代价换取时间代价的算法。 2. 编程题1、2的递归方程    3. 结对编程情况    本次结对编程将较多时间花在了讨论讨论动态规划的思想上,并没有在课堂上完全解决所有实践题目,仍需提高课堂解决问题的效率。与编程伙伴在讨论过程中分别对同一问题进行备忘录方法和和非递归动态规划算法的实操,明白了备忘录方法即使避免了子问题被重复计算,但其递归算法仍然有可能造成栈溢出,因此求解具有最优子结构性质且子问题重叠的问题,最好采用非递归的动态规划算法。 来源: https://www.cnblogs.com/gdufsczg/p/11783761.html