数据结构与算法--递归(recursion)
递归的概念
简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
递归调用机制
我列举两个小案例,来帮助大家理解递归
1、打印问题
2、阶乘问题
//输出什么?
public static void test(int n) {
if (n > 2) {
test(n - 1);
}
System.out.println("n=" + n);
} //阶乘
public static int factorial(int n) {
if (n == 1) {
return 1;
} else {
return factorial(n - 1) * n;
}}
3、使用图解说明递归的调用机制
递归能解决什么样的问题
1、各种数学问题如: 8皇后问题 , 汉诺塔, 阶乘问题, 迷宫问题, 球和篮子的问题(google编程大赛)
2、各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等.
3、将用栈解决的问题-->第归代码比较简洁
递归需要遵守的重要规则
1)执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
2)方法的局部变量是独立的,不会相互影响, 比如n变量
3)如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.
4)递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError,死龟了:)
5)当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
递归应用场景
迷宫问题(回溯), 递归(Recursion)
迷宫问题:将左上角小球一步一步走到右下角位置。怎么走?
分析:
1、我们可以用一个二维数组map[8][7]表示地图,i,j 表示从地图的哪个位置开始出发 (1,1)
2、如果小球能到 map[6][5] 位置,则说明通路找到.
3、约定: 当map[i][j] 为 0 表示该点没有走过 当为 1 表示墙 ; 2 表示通路可以走 ; 3 表示该点已经走过,但是走不通
4、在走迷宫时,需要确定一个策略(方法) 下->右->上->左 , 如果该点走不通,再回溯
实现代码:
/**
*
* @param map 表示地图
* @param i 从哪个位置开始找
* @param j
* @return 如果找到通路,就返回true, 否则返回false
*/
public static boolean setWay(int[][] map, int i, int j) {
if(map[6][5] == 2) { // 通路已经找到ok
return true;
} else {
if(map[i][j] == 0) { //如果当前这个点还没有走过
//按照策略 下->右->上->左 走
map[i][j] = 2; // 假定该点是可以走通.
if(setWay(map, i+1, j)) {//向下走
return true;
} else if (setWay(map, i, j+1)) { //向右走
return true;
} else if (setWay(map, i-1, j)) { //向上
return true;
} else if (setWay(map, i, j-1)){ // 向左走
return true;
} else {
//说明该点是走不通,是死路
map[i][j] = 3;
return false;
}
} else { // 如果map[i][j] != 0 , 可能是 1, 2, 3
return false;
}
}
}
public static void main(String[] args) {
// 先创建一个二维数组,模拟迷宫
// 地图
int[][] map = new int[8][7];
// 使用1 表示墙
// 上下全部置为1
for (int i = 0; i < 7; i++) {
map[0][i] = 1;
map[7][i] = 1;
} // 左右全部置为1
for (int i = 0; i < 8; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
//设置挡板, 1 表示
map[3][1] = 1;
map[3][2] = 1;
// map[1][2] = 1;
// map[2][2] = 1; // 输出地图
System.out.println("地图的情况");
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
} //使用递归回溯给小球找路
setWay(map, 1, 1);
//setWay2(map, 1, 1); //输出新的地图, 小球走过,并标识过的递归
System.out.println("小球走过,并标识过的 地图的情况");
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 7; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
} }
输出 地图的情况
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
小球走过,并标识过的 地图的情况
1 1 1 1 1 1 1
1 2 0 0 0 0 1
1 2 2 2 0 0 1
1 1 1 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 0 0 1
1 0 0 2 2 2 1
1 1 1 1 1 1 1
上面代码示例 不走策略是 下->右->上->左 ,那么我们也可以改变策略,改成 上->右->下->左 ,那又怎么写,会怎么走呢。
就是改变上面代码 if else 顺序即可。
这就是简单运用 递归 回溯算法的应用。
数据结构与算法--递归(recursion)的更多相关文章
- Java数据结构和算法 - 递归
三角数字 Q: 什么是三角数字? A: 据说一群在毕达哥拉斯领导下工作的古希腊的数学家,发现了在数学序列1,3,6,10,15,21,……中有一种奇特的联系.这个数列中的第N项是由第N-1项加N得到的 ...
- java 数据结构与算法---递归
原理来自百度百科 一.递归的概念 程序调用自身的编程技巧称为递归( recursion).递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通 ...
- js数据结构与算法--递归
递归,函数自己调用自己 return 返回值, 后面的代码不执行 function fn(num){ console.log(num) if(num == 0){ return; } fn(num-1 ...
- 算法与数据结构基础 - 递归(Recursion)
递归基础 递归(Recursion)是常见常用的算法,是DFS.分治法.回溯.二叉树遍历等方法的基础,典型的应用递归的问题有求阶乘.汉诺塔.斐波那契数列等,可视化过程. 应用递归算法一般分三步,一是定 ...
- 数据结构和算法(Golang实现)(8.2)基础知识-分治法和递归
分治法和递归 在计算机科学中,分治法是一种很重要的算法. 字面上的解释是分而治之,就是把一个复杂的问题分成两个或更多的相同或相似的子问题. 直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合 ...
- 数据结构与算法 Big O 备忘录与现实
不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新. 算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...
- 用python语言讲解数据结构与算法
写在前面的话:关于数据结构与算法讲解的书籍很多,但是用python语言去实现的不是很多,最近有幸看到一本这样的书籍,由Brad Miller and David Ranum编写的<Problem ...
- [0x00 用Python讲解数据结构与算法] 概览
自从工作后就没什么时间更新博客了,最近抽空学了点Python,觉得Python真的是很强大呀.想来在大学中没有学好数据结构和算法,自己的意志力一直不够坚定,这次想好好看一本书,认真把基本的数据结构和算 ...
- 为什么我要放弃javaScript数据结构与算法(第十一章)—— 算法模式
本章将会学习递归.动态规划和贪心算法. 第十一章 算法模式 递归 递归是一种解决问题的方法,它解决问题的各个小部分,直到解决最初的大问题.递归通常涉及函数调用自身. 递归函数是像下面能够直接调用自身的 ...
随机推荐
- radioButon的使用
界面: <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android=& ...
- 2018 遇到selenium.common.exceptions.WebDriverException问题
selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PAT ...
- 【Tomcat】Tomcat 配置JNDI数据源(三)
数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下: ①加载数据库驱动程序(Class.forName("数据库驱动类");) ②连接数据库(Connec ...
- word xml 各个标签含义
@参考文章 <w:p> <!--表示一个段落--> <w:val > <!--表示一个值--> <w:r> <!--表示一个样式串,指 ...
- Asynchronous Streaming Request Processing in Spring MVC 4.2 + Spring Boot(SpringBoot中处理异步流请求 SpringMvc4.2以上)
With the release of Spring 4.2 version, Three new classes have been introduced to handle Requests As ...
- expect 实现自动交互脚本
1. 说明 在编写脚本时,可能会遇到需要在另一台主机上执行一个命令,或者在本机拷贝另一台主机内的一个文件.如果两台主机之间没有做互信,就会牵扯到用户输入密码的交互过程,这对编写自动脚本来说, 就行不通 ...
- LODOP的ADD_PRINT_TABLE中不能总计在最后一页显示在tfoot后面
ADD_PRINT_TABLE有计算功能,还会每页显示tfoot和thead里的内容.相关其他博文:如果一个表格既有需要每页显示的tfoot,还有一个总计功能,想显示在最后一页的tfoot后面,是不行 ...
- Cas(09)——通过Proxy访问其它Cas应用
通过Proxy访问其它Cas应用 目录 1.1 原理 1.2 配置 1.2.1 代理端 1.2.2 被代理端 1.3 请求示例 考虑这样一种场景:有两个应用App1 ...
- CF1227D Optimal Subsequences
思路: 首先对于单个查询(k, p)来说,答案一定是a数组中的前k大数.如果第k大的数字有多个怎么办?取索引最小的若干个.所以我们只需对a数组按照值降序,索引升序排序即可. 多个查询怎么办?离线处理. ...
- [BJOI2019] 奥术神杖 [取log+AC自动机+dp]
题面 传送门 思路 首先,看到这个乘起来开根号的形式,应该能想到用取$\log$的方式做一个转化: $\sqrt[n]{\prod_i a_i}=\frac{1}{n}\sum_i \log_b a_ ...