Java-递归算法

说到递归就想到小时候听到的一个有趣的故事,故事是这样的:“从前有座山,山上有座庙,庙里有一个老和尚,老和尚对小和尚讲着一个故事,故事是这样的:从前有座山,山上有座庙,庙里有一个老和尚,老和尚对小和尚讲着一个故事......”。这个故事里就有递归思想的体现。

1.什么是递归算法?

  简单的说递归算法就是直接或间接的调用自身算法的过程。

2.特点

(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序

注意:(1) 方法内部调用自己方法不能100%成立,否则是死循环,就是说递归必须有出口,有明确的递归条件,知道程序执行到那就不再递归。
          (2) 递归层次尽量少,因为递归消耗内存可观,运行效率差

3.递归求n阶乘

问题:利用递归求5!

代码:

public class Test1 {
	public static void main(String[] args) {
		System.out.println(factorial(5));
	}
	public static int factorial(int n){
		if(n==1){//递归结束条件
			return 1;
		}
		return n*factorial(n-1);
	}
}


4.Fibonacci数列

问题:斐波那契数列指的是这样一个数列:1、1、2、3、5、8、13、21、34、……

代码:

public class Test2 {
	public static void main(String[] args) {
		System.out.println(fun(7));
	}
	public static int fun(int n){
		if(n==1||n==2){
			return 1;
		}
		return fun(n-1)+fun(n-2);
	}
}

5.全排列

问题:从n个元素中任取m个元素,并按照一定的顺序进行排列,称为排列,当n==m时,称为全排列,

例如:参数"abc"-----> 全排列 输出:abc  acb  bac  bca  cab  cba

代码:

public class Test3 {
	
	/**
	 * 算法思路:
	 * 1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀)
	 * 2)出口:如果只有一个元素的全排列,则说明已经排完,则输出数组
	 * 3)不断将每个元素放做第一个元素,然后将这个元素作为前缀,并将其余元素继续全排列,
	 * 等到出口,出口出去后还需要还原数组
	 */
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入要排序的元素:");
		String str = scanner.nextLine().trim();
		char[] ch = str.toCharArray();
		System.out.println("全排列后的元素:");
		permute(ch, 0, ch.length-1);
		
	}
	
	/**
	 * 对数组ch中元素进行全排列
	 * @param ch 排列数组
	 * @param low 数组起始下标 0
	 * @param high 数组末下标 ch.length-1
	 */
	public static void permute(char[] ch, int low,int high){
		
		if(low==high){//递归出口
			for (int i = 0; i <=high; i++) {
				System.out.print(ch[i]);
			}
			System.out.println();
		}else{
			for (int j = low; j <=high; j++) {
				//依次把low-high的元素作为排序开始
				char temp = ch[j];
				ch[j] = ch[low];
				ch[low]=temp;
				//第一个位置已排好,接着递归排low+1~high位置
				permute(ch, low+1, high);
				
				//排完后要恢复源状态
				temp=ch[low];
				ch[low]=ch[j];
				ch[j]=temp;
			}
		}
	}
}
6.汉诺塔问题

问题:汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?


代码:

public class Test4 {
	
	private static int n = 0;//标记移动次数
	
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		char A = 'A';
		char B = 'B';
		char C = 'C';
		System.out.println("输入圆盘的个数:");
		int disks = scanner.nextInt();
		Test5.hanoi(disks, A, B, C);
		System.out.println("^_^移动了"+n+"次,把A上的圆盘都移动到了C上");
	}
	
	/**
	 * 打印圆盘每次从起始塔移动到目标塔
	 * @param disks 圆盘个数
	 * @param A 起始塔
	 * @param C 目标塔
	 */
	public static void move(int disks,char A,char C){
		System.out.println("第"+(++n)+"次移动:"+"把"+disks+"号圆盘从"+A+"-->"+C);
	}
	
	/**
	 * 递归实现汉诺塔的移动
	 * @param n 盘子的编号
	 * @param A A塔
	 * @param B B塔
	 * @param C C塔
	 */
	public static void hanoi(int n,char A,char B,char C){
		//圆盘只有一个时,只需从A塔移到C塔
		if(n==1){
			//将编号为1的圆盘从A号移到C上
			Test5.move(1, A, C);
		}else{
			//递归,把A塔上编号为1~n-1的圆盘移到B上,以C为辅助塔
			hanoi(n-1, A, C, B);
			//把A塔上编号为n的圆盘移动C上
			Test5.move(n, A, C);
			//递归,把B塔上编号为1~n-1的圆盘移到C上,以A为辅助塔
			hanoi(n-1, B, A, C);
		}
	}
}

7.面试题1

问题:要求计算1+2+3+4+...+100并输出结果,在这段代码中不能出现for,while关键字

代码:

public class Test5 {
	public static void main(String[] args) {
		System.out.println(sum(100));
	}
	
	public static int sum(int n){
		int result;
		if(n<=0){
			result = 0;
		}else{
			result = n+sum(n-1);
		}
		return result;
	}
}

8.面试题2

问题:一个人买汽水,1块钱1瓶汽水,3个瓶盖可以换1瓶汽水,2个空瓶可以换一瓶汽水,问:20块钱可以买多少瓶汽水?

代码:

public class Test6 {
	public static void main(String[] args) {
		System.out.println(20+sum(20,20));
	}
	
	/**
	 * 最多可以买多少瓶汽水(不考虑先借一瓶喝完再还的情况)
	 * @param a:瓶盖的数量
	 * @param b:空瓶的数量
	 */
	public static int sum(int a,int b){
		
		//瓶盖小于3个同时空瓶小于2个
		//递归终止
		if(a<3&&b<2){
			return 0;
		}
		
		//瓶盖换取汽水的个数
		int cap1 = a/3;
		//换取汽水后剩余的瓶盖数
		int cap2 = a%3;
		
		//空瓶获取汽水的个数
		int bottle1 = b/2;
		//换取汽水后剩余的空瓶数
		int bottle2 = b%2;
		
		return cap1+bottle1+sum(cap1+cap2+bottle1,bottle1+bottle2+cap1);
	}
}


9.文件目录相关的递归

问题:统计目前你写的java文件中有多少行代码?

代码:

public class Counter {
	
	private int lines = 0;
	
	public static void main(String[] args) {
		Counter counter = new Counter();
		File dir = new File("D:\\workspace");
		try {
			counter.count(dir);
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println(counter.lines);
	}
	
	private void count(File dir) throws IOException {
		//找到全部Java文件,统计每个文件中行数增加到lines
		File[] files = dir.listFiles();
		//找到全部子文件夹,统计每个子文件夹
		for (File file : files) {
			if(file==null){
				continue;
			}
			if(file.isFile()){
				if(file.getName().endsWith(".java")){
					lines +=lines(file);
				}
			}else{
				count(file);
			}
		}
	}
	
	private int lines(File file) throws IOException {
		System.out.println(file.getAbsolutePath());
		BufferedReader br = new BufferedReader(new FileReader(file));
		
		int n = 0;
		String str = null;
		while((str=br.readLine())!=null){
			if(str.trim().isEmpty()){
				continue;
			}
			n++;
		}
		br.close();
		return n;
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值