【韩顺平Java笔记】第7章:面向对象编程(基础部分)【214-226】

server/2024/10/20 6:37:48/

文章目录

  • 214. 递归解决什么问题
  • 215. 递归执行机制1
  • 216. 递归执行机制2
  • 217 递归执行机制3
  • 217.1 阶乘
  • 218. 递归执行机制4
  • 219. 斐波那契数列
  • 220. 猴子吃桃
  • 221. 222. 223. 224. 老鼠出迷宫1,2,3,4
    • 224.1 什么是回溯
  • 225. 汉诺塔
  • 226. 八皇后

214. 递归解决什么问题

简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂问题,同时可以让代码变得简洁
递归能解决的问题:

215. 递归执行机制1

public class TestUse {public static void main(String[] args) {T t1 = new T();t1.test(4);}
}
class T{//分析public void test(int n){if(n > 2){test(n-1);}System.out.println("n=" + n);}
}

运行结果:
n=2
n=3
n=4
函数调用栈过程:

【注】每一个栈都会完整的执行方法,在哪里调用就在哪里返回。

216. 递归执行机制2

将上一节课的代码的if条件假如else如下

java">public void test(int n){if(n > 2){test(n-1);}else{System.out.println("n=" + n);}}

就变成结果只有
n=2
其函数调用栈相当于下图:

217 递归执行机制3

217.1 阶乘

java">public class TestUse {public static void main(String[] args) {T t1 = new T();int res = t1.factorial(5);System.out.println("5 的阶乘 res =" + res);}
}
class T{//分析public void test(int n){if(n > 2){test(n-1);}else{System.out.println("n=" + n);}}//factorialpublic int factorial(int n){if(n == 1){return 1;}else{return factorial(n-1)*n;}}
}

运行结果:
5 的阶乘 res =120

218. 递归执行机制4

219. 斐波那契数列

请使用递归的方式求出斐波那契数1,1,2,3,5,8,13…给你一个整数 n n n,求出它的值是多少

java">public class TestUse {public static void main(String[] args) {T t1 = new T();int n = 7;int res = t1.fib(n);if(res != -1) {System.out.println("当 n="+ n +" 对应的斐波那契数=" + res);}}
}
class T{//Fib数列public int fib(int n){//n小于等于0,提示数据不合法退出if(n <= 0){System.out.println("数据不合法!");return -1;}//第1项和第2项都是1,//第3项开始//fib(n) = fib(n-1) + fib(n-2)if(n == 1 || n == 2){return 1;}else{return fib(n-1) + fib(n-2);}}
}

运行结果:
当 n=7 对应的斐波那契数=13

220. 猴子吃桃

猴子吃桃子问题:有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个,以后每天猴子都吃其中的一半,然后再多吃一个。当到第10天时,想再吃时(即还没吃),发现只有1个桃子了。问题:最初共多少个桃子?(我以前写过一个循环的版本,现在用递归写,看来有些数据要写死了,比如第10天就得固定下来)

java">public class TestUse {public static void main(String[] args) {T t1 = new T();//桃子问题int day = 1;int peachNum = t1.func(day);if(peachNum != -1) {System.out.println("第 " + day + "天有" + peachNum + "个桃子");}}
}
class T{//求解猴子吃桃问题//设func(day)表示day天吃桃子前的桃子数量//day当天吃掉了func(day) / 2 + 1//day当天还剩下func(day) - (func(day) / 2 + 1)=func(day) / 2 - 1//则func(day) = (当天剩下的 + 1)*2//day = 10,剩下1个桃子,func(10) = (1 + 1) * 2//dat = 9,剩下4个桃子,func(9) = (4 + 1) * 2//day = 8,剩下10个桃子,func(8) = (10 + 1) * 2//得出公式,func(day) = (当天剩下的(即下一天的桃子总数func(day + 1)) + 1)*2public int func(int day){//第10天的时候,跳出递归,返回1(剩下1个桃子)if(day == 10){return 1;}else if(day >= 1 && day <= 9){//在其他天数返回刚才推理的公式return (func(day + 1) + 1) * 2;}else{System.out.println("day 在 1-10");return -1;}}
}

运行结果:
第 1天有1534个桃子

221. 222. 223. 224. 老鼠出迷宫1,2,3,4

java">public class TestUse {public static void main(String[] args) {//设置二维数组表示迷宫//8x7二维数组int[][] map = new int[8][7];//0表示可以走,1表示障碍物//将最上面一行和最下面一行,全部设置为1for(int i = 0; i < 7;i++){map[0][i] = 1;map[7][i] = 1;}//最左侧和最右侧列都设置为1for(int j = 0; j < 8;j++){map[j][0] = 1;map[j][6] = 1;//一共7列,最后一列下标为7-1 == 6}//第4行第2,3列元素也是障碍物map[3][1] = 1;map[3][2] = 1;//输出当前地图System.out.println("当前地图情况:");for (int i = 0; i < map.length; i++) {for (int j = 0; j < map[i].length; j++) {System.out.print(map[i][j] + "\t");}System.out.println();}//使用findWay给老鼠找路T t1 = new T();t1.findWay(map, 1, 1);System.out.println("老鼠找路情况:");for (int i = 0; i < map.length; i++) {for (int j = 0; j < map[i].length; j++) {System.out.print(map[i][j] + "\t");}System.out.println();}}
}
class T{//使用递归回溯的思想来解决老鼠出迷宫//findWay方法就是专门来找迷宫的路径//如果找到返回true,否则返回false//map就是二维数组,即表示迷宫//初始位置在下标(1,1),老鼠到达(6,5)代表出迷宫//i,j就是老鼠现在的位置,初始化为(1,1)//因为我们是递归的找路,所以我先规定 map数组的各个值得含义//0可以走 1表示障碍物 2表示可以走(老鼠走过的路径) 3曾经走过但是死路//map[6][5] = 2,即到终点,能走通//先确定老鼠找路得策略,下->右->上->左public boolean findWay(int[][] map, int i, int j){if(map[6][5] == 2){return true;//找到}else{//当前这个位置0,说明可以走if(map[i][j] == 0){//我们假定可以走通map[i][j] = 2;//使用策略,来确定该位置是否真的可以走通//先尝试向下走if(findWay(map, i + 1, j)){return true;}//走不通,再尝试向右走else if(findWay(map, i, j+1)){return true;}//走不通,再尝试向上走else if(findWay(map, i - 1, j)){return true;}//走不通,再尝试向左走else if(findWay(map, i, j - 1)){return true;}//四个方向都走不通,说明假定能走通是错的else{map[i][j] = 3;return false;}}else{//map[i][j] = 1, 2, 3return false;//}}}
}

运行结果:
当前地图情况:
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

修改策略:上右下左

java">public class TestUse {public static void main(String[] args) {//设置二维数组表示迷宫//8x7二维数组int[][] map = new int[8][7];//0表示可以走,1表示障碍物//将最上面一行和最下面一行,全部设置为1for(int i = 0; i < 7;i++){map[0][i] = 1;map[7][i] = 1;}//最左侧和最右侧列都设置为1for(int j = 0; j < 8;j++){map[j][0] = 1;map[j][6] = 1;//一共7列,最后一列下标为7-1 == 6}//第4行第2,3列元素也是障碍物map[3][1] = 1;map[3][2] = 1;//输出当前地图System.out.println("当前地图情况:");for (int i = 0; i < map.length; i++) {for (int j = 0; j < map[i].length; j++) {System.out.print(map[i][j] + "\t");}System.out.println();}//使用findWay给老鼠找路T t1 = new T();t1.findWay2(map, 1, 1);System.out.println("老鼠找路情况:");for (int i = 0; i < map.length; i++) {for (int j = 0; j < map[i].length; j++) {System.out.print(map[i][j] + "\t");}System.out.println();}}
}
class T{//使用递归回溯的思想来解决老鼠出迷宫//findWay方法就是专门来找迷宫的路径//如果找到返回true,否则返回false//map就是二维数组,即表示迷宫//初始位置在下标(1,1),老鼠到达(6,5)代表出迷宫//i,j就是老鼠现在的位置,初始化为(1,1)//因为我们是递归的找路,所以我先规定 map数组的各个值得含义//0可以走 1表示障碍物 2表示可以走(老鼠走过的路径) 3曾经走过但是死路//map[6][5] = 2,即到终点,能走通//先确定老鼠找路得策略,下->右->上->左public boolean findWay(int[][] map, int i, int j){if(map[6][5] == 2){return true;//找到}else{//当前这个位置0,说明可以走if(map[i][j] == 0){//我们假定可以走通map[i][j] = 2;//使用策略,来确定该位置是否真的可以走通//先尝试向下走if(findWay(map, i + 1, j)){return true;}//走不通,再尝试向右走else if(findWay(map, i, j+1)){return true;}//走不通,再尝试向上走else if(findWay(map, i - 1, j)){return true;}//走不通,再尝试向左走else if(findWay(map, i, j - 1)){return true;}//四个方向都走不通,说明假定能走通是错的else{map[i][j] = 3;return false;}}else{//map[i][j] = 1, 2, 3return false;//}}}//修改策略,看看路径是否有变化//下->右->上->左  ==> 上->右->下->左public boolean findWay2(int[][] map, int i, int j){if(map[6][5] == 2){return true;//找到}else{//当前这个位置0,说明可以走if(map[i][j] == 0){//我们假定可以走通map[i][j] = 2;//使用策略,来确定该位置是否真的可以走通//先尝试向上走if(findWay2(map, i - 1, j)){return true;}//走不通,再尝试向右走else if(findWay2(map, i, j+1)){return true;}//走不通,再尝试向下走else if(findWay2(map, i + 1, j)){return true;}//走不通,再尝试向左走else if(findWay2(map, i, j - 1)){return true;}//四个方向都走不通,说明假定能走通是错的else{map[i][j] = 3;return false;}}else{//map[i][j] = 1, 2, 3return false;//}}}
}

运行结果:
当前地图情况:
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 2 2 2 2 1
1 0 0 0 0 2 1
1 1 1 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 1 1 1 1 1 1

224.1 什么是回溯


在下标(2,2)处设置障碍物,小球先向下走,可以走通,到达下标(1,2),然后测试发现上下左右都走不通(上走不通是因为之前走过1,1下标点),于是它回到上一个栈,然后根据刚才走的情况,判断向右走

后面能用数据结构算法求出最短路径

225. 汉诺塔

汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着 64 片圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
假如每秒钟移动一次,共需多长时间呢?移完这些金片需要 5845.54 亿年以上,太阳系的预期寿命据说也就是数百亿年。真的过了 5845.54 亿年,地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭

  • 思路
    如果A塔只有一个盘子,直接从A塔移动到C塔
    如果A塔有很多盘子,把最后一个盘子上面的所有盘子视为一个盘子,将A塔上面这个盘子堆移动到B塔,然后将A塔最下面的盘子移动到C塔,最后将B塔这一堆移动到C塔,递归思想只考虑这个中间过程和跳出递归的过程。
java">public class TestUse {public static void main(String[] args) {T t = new T();t.move(5, 'A', 'B', 'C');}
}
class T{//n是盘子数,a,b,c是三个塔,C是此次调用move要移动到的位置,A是此次调用时,某个要移动的盘子所在的位置,确定A C后,B也就能确定了public void move(int n, char a, char b, char c){//n<1,提示数据不合法if(n < 1){System.err.println("数据不合法!");}//如果只有一个盘,直接从A移动到Cif(n == 1){System.out.println(a + "->" + c);}else{//有多个盘子,先将上面n-1个盘子视为一个整体,移动到B,借助C,move的参数c是要移动的位置move(n-1, a, c, b);//把下面这个盘移动到CSystem.out.println(a + "->" + c);//再把B塔的所有盘移动到C,借助A//c = c, a = b,剩下 amove(n-1, b, a, c);}}
}

运行结果:
A->C
A->B
C->B
A->C
B->A
B->C
A->C
A->B
C->B
C->A
B->A
C->B
A->C
A->B
C->B
A->C
B->A
B->C
A->C
B->A
C->B
C->A
B->A
B->C
A->C
A->B
C->B
A->C
B->A
B->C
A->C

226. 八皇后

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于 1848 年提出:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

java">public class TestUse {public static void main(String[] args) {int arr[] = new int[8];T t = new T();t.eightQueen(arr, 0);}
}
class T{public int solNum = 0;//记录解法个数的成员//八皇后,n表示所在行数,如果n为棋盘行数,则说明已经放好了//即跳出递归的条件//max是棋盘行数public void eightQueen(int[] arr, int n){if(n == arr.length){//放好后打印八皇后solNum++;System.out.println("解法" + solNum + ":");for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr.length; j++) {//如果arr[i]==j,打印,对应的是下标i行j列有皇后if(arr[i] == j){System.out.print("o\t");}else{System.out.print("#\t");}}System.out.println();}return;}//依次在第n行放入皇后判断是否冲突,i代表当前行的列下标for (int i = 0; i < arr.length; i++) {//假定可以放arr[n] = i;//判断是否可以放,如果可以则继续放if(judge(arr, n)){eightQueen(arr, n+1);}}}//判断当前位置是否可行的方法public boolean judge(int[] arr, int n){//判断当前位置是否有冲突for(int j = 0; j < n; j++){//n+1是当前第n+1个皇后arr[n]//如果当前皇后和前n+1-1=n个皇后在同一列或者同一对角线上,就发生冲突,则返回falseif(arr[j] == arr[n] || Math.abs(n - j) == Math.abs(arr[n] - arr[j])){return false;}}//全部走一遍,前n个没问题,就说明可以放置return true;}
}

运行结果
……太长了,直接看最后
解法92:
# # # # # # # o
# # # o # # # #
o # # # # # # #
# # o # # # # #
# # # # # o # #
# o # # # # # #
# # # # # # o #
# # # # o # # #

一共是92种解法,确实难想到,我也是查了好多资料,本科算法课忘得差不多了。


http://www.ppmy.cn/server/127420.html

相关文章

【Text2SQL】当前在BIRD基准测试集上取得SOTA的论文

论文《The Death of Schema Linking? Text-to-SQL in the Age of Well-Reasoned Language Models》探讨了在大型语言模型&#xff08;LLMs&#xff09;时代&#xff0c;文本到SQL&#xff08;Text-to-SQL&#xff09;转换中模式链接&#xff08;Schema Linking&#xff09;的作…

ARM Process state -- PSTATE

In the ARMv8-A architecture, Process state or PSTATE is an abstraction of process state information. All of the instruction sets provide instructions that operate on elements of PSTATE. 在ARMv8-A架构中&#xff0c;进程状态或PSTATE是进程状态信息的抽象。所有…

Qt开发第一讲

一、Qt项目里面有什么&#xff1f; 对各个文件的解释&#xff1a; Empty.pro文件 QT core gui # 要引入的Qt模块&#xff0c;后面学习到一些内容的时候可能会修改这里 #这个文件相当于Linux里面的makefile文件。makefile其实是一个非常古老的技术了。 #qmake搭配.pr…

OpenGL ES 顶点缓冲区和布局(3)

OpenGL ES 顶点缓冲区和布局(3) 简述 顶点缓冲区的本质就是一段GPU上的显存&#xff0c;我们通过绑定顶点缓冲区的方式来将数据从CPU传到GPU。 我们之前在绘制三角形的例子中&#xff0c;我们往顶点缓冲区只传入了坐标&#xff0c;但是其实顶点是可以包含很多数据的&#xff…

排序算法——快速排序:普通快排与双路快排

快速排序&#xff1a; 普通快排&#xff1a; 选取待排序数组的首或尾元素作为枢轴&#xff08;就是base&#xff0c;我们选出来的比较的数&#xff09;&#xff0c;大于base的放右边&#xff0c;小于base的放左边。 public void quickSort(int[] nums, int low, int high) {…

微服务(Microservices),服务网格(Service Mesh)以及无服务器运算Serverless简单介绍

文章目录 什么是微服务?一、定义与特点二、优势三、组件与架构四、应用场景五、挑战与解决方案什么是服务网格?一、定义与特点二、核心组件三、主要功能四、实现工具五、应用场景六、优势与挑战什么是Serverless?一、定义与特点二、主要领域三、优势四、应用场景五、挑战三者…

Redis数据库与GO(二):list,set

一、list&#xff08;列表&#xff09; list&#xff08;列表&#xff09;是简单的字符串列表&#xff0c;按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。List本质是个链表&#xff0c; list是一个双向链表&#xff0c;其元素是有序的&#xff0c;元…

PMP--三模--解题--151-160

文章目录 14.敏捷--仆人式领导--在敏捷环境中&#xff0c;项目经理充当仆人式领导&#xff0c;其工作重点转变为引导需要帮助的人&#xff0c;促进团队的合作&#xff0c;保持与干系人的需要一致。151、 [单选] 两个分布在不同地方的团队在同一个项目上。相比A团队&#xff0c;…