• 递归算法案例分析


    一、递归练习(斐波那契数列)

    • 不死神兔
    • 故事得从西元1202年说起,话说有一位意大利青年,名叫斐波那契。
    • 在他的一部著作中提出了一个有趣的问题:假设一对刚出生的小兔一个月后就能长成大兔,再过一个月就能生下一对小兔,并且此后每个月都生一对小兔,一年内没有发生死亡,
    • 问:一对刚出生的兔子,一年内繁殖成多少对兔子?
    算法分析:
    • 1 1 2 3 5 8 13
    • 第一个月一对小兔子 1
    • 第二个月一对大兔子 1
    • 第三个月一对大兔子生了一对小兔子 2
    • 第四个月一对大兔子生了一对小兔子
    • 一对小兔子长成大兔子 3
    • 第五个月两对大兔子生两对小兔子
    • 一对小兔子长成大兔子 5

    我们首先可以用非递归的方法来做这个题目
    private static void demo1() {
    		// 方法一
    		// 用数组做不死神兔
    		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]);
    	}


    然后我们可以用第递归来做,
    	// 第2种方法:用递归求斐波那契数列
    	/*
    	 * 分析: 1=fun(1) 1=fun(2) 2=fun(1)+fun(2) 3=fun(2)+fun(3)
    	 */
    	public static int fun(int num) {
    		if (num == 1 || num == 2) {
    			return 1;
    		} else {
    			return fun(num - 2) + fun(num - 1);
    		}
    	}


    二、集合练习(约瑟夫环)
    • 幸运数字
    /*
    	 * 返回值类型为int
    	 * 
    	 */
    	public static int getLuckNum(int num){
    		//创建集合1到num的对象
    		ArrayList<Integer>  list=new ArrayList<>();
    		for(int i=1;i<=num;i++){
    			list.add(i);    //存储到集合中
    		}
    		int count=1;    //只要是3的倍数就remove掉
    		for(int i=0;list.size()!=1;i++){  //只要集合中人数超过1,就要不断的杀
    			if(i==list.size()){
    				i=0;         //如果i增长到集合最大的索引+1时,就重新归0
    			}
    			if(count%3==0){
    				list.remove(i--);
    				
    			}
    			count++;
    					
    		}
    		return list.get(0);
    	}


    三、
    递归练习(1000的阶乘所有零和尾部零的个数)
    当然,如果我们直接使用以下方法来做的话是不可行的
    /*
    		 * int result=1; //这里要从1开始,不能从0开始,因为任何数乘0都为0 
    		 * for(int i=1;i<=1000;i++){
    		 * 		result=result*i; 
    		 * } 
    		 * 	System.out.println(result);
    		 * //此方法不能使用,因为这样计算的值(1000的阶乘)超出int的取值范围了
    		 */

    所以我们需要这样做,先去求出1000的阶乘,然后再去统计有多少个0.

    // 求出1000的阶乘
    		BigInteger bi1 = new BigInteger("1");
    		for (int i = 1; i <= 1000; i++) {
    			BigInteger bi2 = new BigInteger(i + "");// 转换为字符串类型的
    			bi1 = bi1.multiply(bi2); // 将bi1与bi2相乘的结果赋值给bi1
    		}

    // 求出尾部所有的0
    	private static void demo2(BigInteger bi1) {
    		String str=bi1.toString();
    		StringBuilder sb=new StringBuilder(str);
    		str=sb.reverse().toString();  //链式编程
    		int count=0;
    		for(int i=0;i<str.length();i++){
    			if('0'!=str.charAt(i)){
    				break;
    			}else{
    				count++;
    			}
    		}
    		System.out.println(count);
    	}
    
    	// 求出所有的0
    	private static void demo1(BigInteger bi1) {
    		String str = bi1.toString();// 获取字符串表现形式
    		int count = 0;
    		for (int i = 0; i < str.length(); i++) {
    			if ('0' == str.charAt(i)) { // 如果字符串中出现了0则计数器加1
    				count++;
    			}
    		}
    		System.out.println(count);
    	}
    

    那么如果我们用递归来做的话,这个问题就会非常简单了,

    //求出1000的阶乘所有零和尾部零的个数,用递归做
    public class h {
    
    	public static void main(String[] args) {
    		System.out.println(fun(1000));
    
    	}
    	public static int fun(int num){
    		
    		if(num>0 && num<5){
    			return 0;
    		}else{
    			return num/5 + fun(num/5);
    		}
    	}
    }

    File类递归练习(统计该文件夹大小)
    需求:,从键盘接收一个文件夹路径,统计该文件夹大小

    </pre><pre name="code" class="java">/*
    	 * 从键盘接收一个文件夹路径
    	 * 定义一个无限循环
    	 * 将键盘录入的结果存储并封装成File对象
    	 * 对File对象判断
    	 * 将文件夹路径对象返回
    	 * 
    	 * 
    	 * 统计该文件夹大小
    	 * 1、定义一个求和变量
    	 * 2、获取该文件夹下所有的文件和文件夹listFiles();
    	 * 3、遍历数组
    	 * 4、判断是文件就计算大小并累加
    	 * 5、判断是文件夹就递归调用
    	 * 
    	 * 
    	 */
    
    	public static void main(String[] args){
    		File dir=getDir();
    		System.out.println(getFileLength(dir));
    	}
    	
    	public static File getDir(){
    		Scanner sc=new Scanner(System.in);
    		System.out.println("请输入一个文件夹路径");
    		while(true){
    			String line=sc.nextLine();
    			File dir=new File(line);
    			if(!dir.exists()){
    				System.out.println("目录不存在");
    			}else if(dir.isFile()){
    				System.out.println();
    			}else{
    				return dir;
    			}	
    		}
    	
    	}
    	
    	public static long getFileLength(File dir){
    		long len=0;
    		File[] files=dir.listFiles();
    		for(File file :files){
    			if(file.isFile()){
    				len=len+file.length();
    			}else{
    				len=len+getFileLength(file);
    			}
    		}
    		return len;
    	}




    File类递归练习(删除该文件夹)
    需求:,从键盘接收一个文件夹路径,删除该文件夹

    分析:

    /*
    	 * 1、获取该文件夹下的所有文件和文件夹
    	 * 2、遍历数组
    	 * 3、判断是文件直接删除
    	 * 4、如果是文件夹,递归调用
    	 * 5、循环结束后,把控文件夹删除
    	 * 
    	 */
    
    	public static void main(String[] args) {
    		File dir=a.getDir();
    		deleteFile(dir);
    
    	}
    	public static void deleteFile(File dir){
    		File[] subFiles=dir.listFiles();
    		for(File file:subFiles){
    			if(file.isFile()){
    				file.delete();
    			}else{
    				deleteFile(file);
    			}
    		}
    		//循环结束后把文件夹删除掉
    		dir.delete();
    	}




    File类递归练习(拷贝)
    需求,从键盘接收两个文件夹路径,把其中一个文件夹中(包含内容)拷贝到另一个文件夹中

    /*
    	 * 1、在目标文件夹中创建原文件夹
    	 * 2、获取原文件夹中所有的文件和文件夹,存储在File数组中
    	 * 3、遍历数组
    	 * 4、如果是文件就用io流读写
    	 * 5、如果是文件夹就递归调用
    	 * 
    	 */
    	public static void main(String[] args) throws IOException {
    		File src=a.getDir();
    		File dest=a.getDir();
    		if(src.equals(dest)){
    			System.out.println("目录文件夹是源文件夹的子文件夹");
    		}else{
    			copy(src,dest);
    		}
    	}
    
    	public static void copy(File src, File dest) throws IOException {
    		File newDir=new File(dest,src.getName());
    		newDir.mkdir();
    		File[] subFiles=src.listFiles();
    		for (File file : subFiles) {
    			if(file.isFile()){
    				BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
    				BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(new File(newDir,file.getName())));
    				int b;
    				while((b=bis.read())!=-1){
    					bos.write(b);
    				}
    				bis.close();
    				bos.close();
    			}else{
    				//如果是文件夹就递归调用
    				copy(file,newDir);
    			}
    		}
    		
    	}




    File类递归练习(按层级打印)
    * 要求:,从键盘接收一个文件夹路径,把文件夹中的所有文件以及文件夹的名字按层级打印,

    /*
    	 * 1、获取所有文件和文件夹,返回的File数组
    	 * 2、遍历数组
    	 * 3、无论是文件还是文件夹,都需要直接打印
    	 * 4、如果是文件夹,递归调用
    	 * 
    	 */
    	public static void main(String[] args) {
    		File dir=a.getDir();
    		printLev(dir,0);
    		
    	}
    
    	public static void printLev(File dir,int level) {
    		File[] subFiles=dir.listFiles();
    		for (File file : subFiles) {
    			for(int i=0;i<=level;i++){
    				System.out.print("	");
    			}
    			System.out.println(file);
    			if(file.isDirectory()){
    				printLev(file,level+1);
    			}
    		}
    		
    	}
    






  • 相关阅读:
    C#基础知识之静态和非静态
    C#基础知识之类和结构
    jQuery选择器
    ajax和json的优缺点
    说几条JavaScript的基本规范
    vue中异步请求渲染问题(swiper不轮播)(在开发过程中遇到过什么问题、踩过的坑)
    vue响应数据的原理
    面向对象的几种方式(创建对象的几种方式)
    ES6新特性
    HTML和XHTML的区别
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6314853.html
Copyright © 2020-2023  润新知