前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

递归

作者头像
微醺
发布2019-01-17 12:58:19
7520
发布2019-01-17 12:58:19
举报

递归

什么是递归,为什么使用递归?

递归就是函数或者方法自己调用自己的过程。在生活中,我们睡觉,闹钟叫我们起床就可以看做一个递归的过程。我们每天睡觉就可以看做成函数的执行。每天都要睡觉,这就是函数的循环执行。只要到时间点我们就会自己去睡觉,这可以看做是自我函数的调用。每个递归函数必须有出口,而这个闹钟就是出口。闹钟一响我们就停止睡觉,干我们自己的事情。人没有闹钟就会睡过头,函数没有出口,函数就会变成死循环。我个人认为递归就是循环的特殊的一种。下面从几个例子来探索递归的奥秘。

不死神兔

故事得从西元1202年说起,话说有一位意大利青年,名叫斐波那契。 在他的一部著作中提出了一个有趣的问题:假设一对刚出生的小兔一个月后就能长成大兔,再过一个月就能生下一对小 兔,并且此后每个月都生一对小兔,一年内没有发生死亡, 问:一对刚出生的兔子,一年内繁殖成多少对兔子? 1 2 3 4 5 6 7 8 月 1 1 2 3 5 8 13 21 对兔子 1 = fun(1) 1 = fun(2) 2 = fun(1) + fun(2) 3 = fun(2) + fun(3) 这样就可以分析出来这道题主要的意思了

代码语言:javascript
复制
public static void main(String[] args) {
		System.out.println(fun(12));//输出一年繁殖的兔子数
	}  	
	public static int fun(int num){
		if(num==1||num==2)return 1;/方法的出口
		else return fun(num-2)+fun(num-1);//不是出口就继续调用自己
	}

使用数组也可以做

代码语言:javascript
复制
public static void main(String[] args) {
		//数组做不死神兔
		int[] arr=new int[12];
		arr[0]=1;//第一个月的兔子数
		arr[1]=1;//第二月的兔子数
		//遍历数组给其他元素赋值
		for (int i = 2; i < arr.length; i++) {//从第三个月开始,后面的兔子对数是前面月兔子的和
			arr[i]=arr[i-2]+arr[i-1];
		}
		System.out.println(arr[arr.length-1]);//输出1年的兔子对数
	}
幸运数字

故事:发生西汉某年的一个早晨,皇上闲来无事,叫来一群犯人,玩一个叫做幸运数字的游戏。就是,所有人围成一个圆圈,如果是3的倍数就拉出去斩了。最后只有一个人活了下来。请问如果一共八个人,这个幸运数字是几?

代码语言:javascript
复制
public static void main(String[] args) {
		System.out.println(getLucklyNum(8));//输出幸运数字
	}    
	/**
	 * 获取幸运数字 1.返回值类型 int 2.参数列表 int num
	 */    
	private static int getLucklyNum(int num) {
		// 创建集合存储1到num的对象
		ArrayList<Integer> list = new ArrayList<>();
		for (int i = 1; i <= num; i++) {
			list.add(i);//把数字存到集合中
		}
		// 用来数数的,只要是3的倍数就杀人
		int count = 1;
		// 只要集合中人数超过1,就不断的杀
		for (int i = 0; list.size() != 1; i++) {
			// 如果i增长到集合最大的索引+1时
			if (i == list.size()) {
				// 重新归零
				i = 0;
			}
			if (count % 3 == 0) {
				// 是3的倍数就杀人
				list.remove(i--);
			}
			count++;
		}
		return list.get(0);//返回最后一个人
	}
打印文件夹中的所有文件
代码语言:javascript
复制
  需求:从键盘接收一个文件夹路径,把文件夹中的所有文件以及文件夹的名字按层级打印, 例如:把文件夹中的所有文件以及文件夹的名字按层级打印。
  分析:
  1,获取所有文件和文件夹,返回的File数组
  2,遍历数组
  3,无论是文件还是文件夹,都需要直接打印
  4,如果是文件夹,递归调用

public static void main(String[] args) {
		File dir=getDir();//获取文件对象
		priintLevel(dir,0);
	}
	public static File getDir(){
		// 1,创建键盘录入对象
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入文件夹路径:");
		// 定义个无限循环 如果是文件就输出一句话,是文件夹就返回
		while (true) {
			String str = sc.nextLine();
			File dir = new File(str);
			// 判断文件是否存在
			if (!dir.exists()) {
				System.out.println("你输入的文件夹路径错误!");
			} else if (dir.isFile()) {
				System.out.println("你输入的是文件路径,请重新输入!");
			} else {
				return dir;
			}
		}
	}
	public static void priintLevel(File dir, int n) {
		// 获取所有的文件和文件夹
		File[] arr = dir.listFiles();
		// 判断如果是文件和文件夹就打印文件名
		for (File file : arr) {
			for (int i = 0; i <n; i++) {
				System.out.println("\t");
			}
			//输出文件名
			System.out.print(file);
			//如果是文件夹,调用本身,输出里面的文件名
			if(file.isDirectory()){
				priintLevel(file,n++);
			}
		}
	}
1000的阶乘所有零和尾部零的个数
首先不用递归
代码语言:javascript
复制
public static void main(String[] args) {
		demo1();//调用demo1方法
		//bi1换成bigInteger,因为1000的阶乘太大
		BigInteger bi1=new BigInteger("1");
		//循环获取1000的阶乘
		for (int i = 1; i < 1000; i++) {
			BigInteger bi2=new BigInteger(i+"");
			bi1=bi1.multiply(bi2);
		}
		//将bi1转成字符串
		String str=bi1.toString();
		//放在stringbuilder中
		StringBuilder sb=new StringBuilder(str);
		//反转字符串
		str=sb.reverse().toString();
		//用来记录0的个数
		int count=0;
		for (int i = 0; i < str.length(); i++) {
			if('0'!=str.charAt(i)){
			//不是0终止循环
				break;
			}else{
			//是0 ,计数器++
				count++;
			}
		}
		System.out.println("尾部零个数:"+count);
	}
	public static void demo1(){
		BigInteger bi1=new BigInteger("1");
		for (int i = 1; i < 1000; i++) {
			BigInteger bi2=new BigInteger(i+"");
			//将bi1与bi2相乘的结果赋值给bi1
			bi1=bi1.multiply(bi2);
		}
		String str=bi1.toString();//获取字符串表现形式
		int count=0;
		for (int i = 0; i < str.length(); i++) {
			if('0'==str.charAt(i)){//如果字符串出现0字符
				count++;
			}
		}
		System.out.println("全部零的个数:"+count);
	}
使用递归

分析:

  • 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 … 1000 1000 / 5 = 200
    • 5 * 5 5 * 5 * 2 5 * 5 * 3 5 * 5 * 4 5 * 5 * 5 5 * 5 * 6 200 / 5 = 40
    • 5 * 5 * 5 * 1 5 * 5 * 5 * 2 5 * 5 * 5 * 3 5 * 5 * 5 * 4 5 * 5 * 5 * 5 5 * 5 * 5 * 6 5 * 5 * 5 * 7 5* 5 * 5 * 8 40 / 5 = 8 8 / 5 = 1

就是看看1000里面有多少个5,1000阶乘,200是5的倍数,200里面有多少个5,200的阶乘,40是5的倍数,40里有多少个5.最后40的阶乘,8是5的倍数,8的阶乘只有1个5.有几个5就有几个0.

代码语言:javascript
复制
 public static void main(String[] args) {       	
     System.out.println("尾部有"+fun(1000)+"个零");
                	}    
                	private static int fun(int num) {
                		if(num>0&&num<5){
                			return 0;
                		}else{
                		return num/5+fun(num/5);
            		}
            	}

总结

递归就是方法或者函数的自我调用,递归一定要有出口,不然就会变成死循环。使用递归可以解决很多循环解决这比较麻烦的问题。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年11月07日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 递归
    • 什么是递归,为什么使用递归?
      • 不死神兔
      • 幸运数字
      • 打印文件夹中的所有文件
      • 1000的阶乘所有零和尾部零的个数
      • 使用递归
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档