[Java]方法递归——经典案例
Posted 迷糊小丸子o_o
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Java]方法递归——经典案例相关的知识,希望对你有一定的参考价值。
Java中的方法递归
-
方法递归
递归是一种算法,在程序设计语言中广泛应用。
方法调用自身的形式称为方法递归(recursion)。 -
递归的形式
直接递归:方法自己调用自己。
间接递归:方法调用其他方法,其他方法又回调方法自己。 -
方法递归注意事项
递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出现象。 -
递归算法三要素
递归的公式
递归的终结点
递归的方向必须走向终结点
通过一些经典案例,加深对方法递归的思想。
文章目录
一、有规律的递归
1.求1-n的和
分析:
此求和问题, 计算方法 f(n) = 1 + 2 + 3 + 4 + 5 + 6 + 7 + …(n-1) + n,含有一定的规律,可总结为:
- 递归公式: f(n) = f(n-1) + n
- 递归终结点:f(1) = 1
- 递归方向:走向终结点 f(1) 的方向
- 如果求1-5的和 的结果,递归思想——先递深,在归回
public class Demo1
public static void main(String[] args)
System.out.println("1-5的和为:"+sum(5));
//递归求和
private static int sum(int n)
if ( n == 1)
return 1;
else
return sum(n-1)+n;
运行结果:
1-5的和为:15
Process finished with exit code 0
2.猴子吃桃问题
分析:
整体来看,每一天都是做同一个事件,典型的规律化问题,考虑递归三要素:
- 递归公式: f(n+1) =1/2 f(n) - 1
化简可得 f(n) = 2f(n+1) + 2 - 递归终结点: f(10)
- 递归方向:走向终结点 f(10) 的方向
public class Demo2
public static void main(String[] args)
System.out.println("一共有"+fun1(1)+"个桃子");
//计算桃子数量
private static int fun1(int n)
if (n == 10)
return 1;
else
return fun1(n+1)*2+2;
运行结果
一共有1534个桃子
Process finished with exit code 0
二、无规律的递归
啤酒问题
分析:
啤酒问题,并不是有规律的计算问题。但是,喝完之后的空瓶、盖子又可以换啤酒,变相来看,又是有规律的计算问题。
解决此类问题,可以将空瓶、盖子转换为金钱问题,转换思想,就是花钱买酒,将复杂的货物交换,转换为简单统一的金钱交换问题,易于解题。
public class Demo3
//定义静态成员变量进行统计最后买的啤酒,默认为0
public static int totalNumber; //记录买的啤酒
public static int totalButtle; //记录上次剩余的瓶子个数
public static int totalCover; //记录上次剩余的盖子个数
public static void main(String[] args)
buy(10);
/**
* 进行买啤酒
* @param money
*/
private static void buy(int money)
int buyNumber = money/2;
totalNumber += buyNumber;
//记录当前的瓶子个数、盖子个数
int buttle = totalButtle + buyNumber;
int cover = totalCover + buyNumber;
//将当前的瓶子和盖子转换为金钱,利用递归再次购买啤酒
int allMoney = 0;
//先判断瓶子和盖子的个数是否满足可以兑换的数量,
if (buttle >= 2)
allMoney += (buttle/2) * 2;
if (cover >= 4)
allMoney += (cover/4) * 2;
//并计算当前剩余的瓶子和盖子的数量
totalButtle = buttle % 2;
totalCover = cover % 4;
//进行判断是否进行递归操作
if (allMoney >= 2)
buy(allMoney);
else
System.out.println(totalNumber+"瓶酒\\t\\t"+totalButtle+"个瓶子\\t\\t"+totalCover+"个盖子");
运行结果:
15瓶酒 1个瓶子 3个盖子
Process finished with exit code 0
三、递归扩展应用
文件搜索
分析:
在对指定文件进行搜索,当我们并不知道指定文件在哪里时,搜索该文件方案是打开当前磁盘,找到所有的文件进行查找;未找到,则从第一个文件夹,一个个打卡进行查找,没有则退出,进入下一个文件,以此类推。
- 先定位出的应该是一级文件对象
- 遍历全部一级文件对象,判断是否是文件
- 如果是文件,判断是否是自己想要的
- 如果是文件夹,需要继续递归进去重复上述过程
/**
* 进行查找磁盘中的一个指定文件的绝对路径
* E:\\Java\\快捷键.md
*/
public class Demo4
public static void main(String[] args)
//一个磁盘,一个文件名
searchFile(new File("E:/"),"快捷键.md");
/**
* 进行文件的查找,并输出其文件的绝对路径
* @param dir 当前查找的目录/文件夹
* @param fileName 所要查找的文件名
*/
private static void searchFile(File dir, String fileName)
//进行判断目录是否为空 或者不是一个目录
if (dir != null && dir.isDirectory())
//获取当前目录下的一级文件
File[] files = dir.listFiles();
if (files != null && files.length > 0)
//进行对数组文件遍历查找
for (File file : files)
//判断文件是否为文件夹,若为文件夹,则进行递归操作
if (file.isFile())
if (file.getName().contains(fileName))
System.out.println(fileName+"文件的绝对路径为:"+file.getAbsolutePath());
else
searchFile(file,fileName);
else
System.out.println("该文件不是一个目录,或者该目录为空!!!!");
运行结果
快捷键.md文件的绝对路径为:E:\\Java\\快捷键.md
Process finished with exit code 0
注意:文件搜索中利用递归的技术,listFiles只能搜索到一级文件对象
java 20 -1 递归的概述和案例
1 /* 2 * 递归:方法定义中调用方法本身的现象 3 * 4 * 方法的嵌套调用,这不是递归。 5 * Math.max(Math.max(a,b),c); 6 * 7 * public void show(int n) { 8 * if(n <= 0) { 9 * System.exit(0); 10 * } 11 * System.out.println(n); 12 * show(--n); 13 * } 14 * 15 * 注意事项: 16 * A:递归一定要有出口,否则就是死递归 17 * B:递归的次数不能太多,否则就内存溢出 18 * C:构造方法不能递归使用 19 * 20 * public DiGuiDemo() { 21 * DiGuiDemo(); 22 * } 23 * 24 * 举例: 25 * A:从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚在给小和尚讲故事,故事是: 26 * 从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚在给小和尚讲故事,故事是: 27 * 从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚在给小和尚讲故事,故事是: 28 * 从前有座山,山里有座庙,庙里有个老和尚和小和尚,老和尚在给小和尚讲故事,故事是: 29 * ... 30 * 出口: 庙挂了,或者山崩了 31 * B:学编程 -- 高薪就业 -- 挣钱 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 挣学费 32 * 学编程 -- 高薪就业 -- 挣钱 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 挣学费 33 * 学编程 -- 高薪就业 -- 挣钱 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 挣学费 34 * 学编程 -- 高薪就业 -- 挣钱 -- 娶媳妇 -- 生娃娃 -- 放羊 -- 挣学费 35 * ... 36 * 出口:娶不到媳妇或者生不了娃娃 37 */ 38 39 40 package zl_DiGui; 41 /* 42 有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少? 43 分析: 44 兔子对数 45 第一个月: 1 46 第二个月: 1 47 第三个月: 2 48 第四个月: 3 49 第五个月: 5 50 第六个月: 8 51 1,1,2,3,5,8... 52 规则: 53 A:从第三项开始,每一项都是前两项之和 54 B:第一第二项都是已知的 55 方法: 56 A:数组 57 B:变量的变化实现 58 第一个月 a=1,b=1; 59 第二个月 a=1,b=2; 60 第三个月 a=2,b=3; 61 第四个月 a=3,b=5; 62 ... 63 每个月的a,是上个月的b,每个月的b,是上个月的a+b 64 C:递归 65 a:返回类型 int 66 b:参数列表 int n (月份) 67 c:出口:n = 1 || n ==2 时,就是第一个月或第二个月时 68 69 */ 70 public class DiGuiDemo1 { 71 72 public static void main(String[] args) { 73 74 //第一种方法:数组 75 int[] ary = new int[20]; 76 ary[0] = 1; 77 ary[1] = 1; 78 79 for(int x = 2; x < ary.length ; x ++){ 80 ary[x] = ary[x - 1] + ary [x - 2]; 81 } 82 System.out.println(ary[19]); 83 84 //第二种方法:变量的变化实现 85 int a = 1; 86 int b = 1; 87 for(int y = 3 ; y <= 20 ; y ++){ 88 int temp = a; 89 a = b; 90 b = temp + a ; 91 } 92 System.out.println(b); 93 94 //调用递归 95 System.out.println(digui(20)); 96 } 97 //递归 98 public static int digui(int n ) { 99 if(n == 1 || n == 2){ 100 return 1; 101 }else{ 102 return digui(n-1) + digui(n-2); 103 } 104 } 105 }
递归解决问题的思想及图解
递归求阶乘的代码实现及内存图解
以上是关于[Java]方法递归——经典案例的主要内容,如果未能解决你的问题,请参考以下文章