递归问题的解题思路

递归问题的解题思路

递归的设计经验

  1. 找重复(子问题)
  • 找到一种划分方法
  • 找到递推公式或者等价转换
    都是父问题转换为求解子问题
  1. 找重复中的变化量
  • 变化的量通常要作为参数
  1. 找参数变化趋势——>设计出口
  • 根据参数变化的趋势,对边界进行控制,适时终止递归

递归的基础练习

1. 切蛋糕思维例题:

1. 求阶乘

 /**
   * f1(n):求n的阶乘-->f1(n-1)求n-1的阶乘
   * 找重复:n*(n-1)的阶乘,求n-1的阶乘是原问题的重复(规模更小)——子问题
   * 找变化:变化的量应该作为参数
   * 找边界:出口*/
public class Demo05
{
	public static void main(String[] args)
	{
		int a=3;
		int result=f1(a);
		System.out.println(result);
	}
	public static int f1(int n)
	{
		if (n==1) return 1;
		return n*f1(n-1);
	}

}

2. 打印从i到j

 /**
   * 打印i到j
   * 找重复:
   * 找变化:变化的量应该作为参数
   * 找边界:出口*/
public static void f2(int i,int j) {
		if (i>j) return;	
		System.out.print(i+" ");		
		f2(i+1,j);	
	}

3. 对arr数组的所有元素求和

public static int f3(int[] arr,int begin)
	{
		if (begin==arr.length-1)
		return arr[begin];
		
		return (arr[begin]+f3(arr, begin+1));
	}

4.翻转字符串

public static String f4(String src,int end) {
		if (end==0)
		{
			return ""+src.charAt(0);//只有一个元素
		}
		return src.charAt(end)+f4(src, end-1);
	}
2.找递推公式或等价转换例题

5.斐波那契数列

//递推公式
	public static int f5(int i) {
		if (i==1||i==2)		
		return 1;
		
		return f5(i-1)+f5(i-2);
	}

6.最大公约数 f(m,n)=f(n,m%n)

//等价转换  f(m,n)=f(n,m%n)辗转相除
public static int f6(int m,int n) {
			if (n==0) return m;
			return f6(n,m%n);	
	}

7.排序改递归

import java.util.Arrays;
public class Main {
	public static void main(String[] args){
  	int arr[]= {9,6,5,8,4,7,1,3,2};
  	insertSort(arr,8);
  	System.out.print(Arrays.toString(arr));//1,2,3,4,5,6,7,8,9
  }
	 public static void insertSort(int []arr,int k) {
		//递归出口
		if(k==0)
			return;
		//对前k-1个元素排序
		insertSort(arr,k-1);
		//把位置k的元素插入到前面的部分
		int x=arr[k];
		int index=k-1;
		while(index>-1&&x<arr[index]) {//小的往前插
			arr[index+1]=arr[index];
			index--;
		}
		arr[index+1]=x;
	}
}

8.汉诺塔

算法分析(递归算法)

实现这个算法可以简单分为三个步骤:
(1) 把n-1个盘子由A 移到 B;
(2) 把第n个盘子由 A移到 C;
(3) 把n-1个盘子由B 移到 C;

从这里入手,在加上上面数学问题解法的分析,我们不难发现,移到的步数必定为奇数步:
(1)中间的一步是把最大的一个盘子由A移到C上去;
(2)中间一步之上可以看成把A上n-1个盘子通过借助辅助塔(C塔)移到了B上,
(3)中间一步之下可以看成把B上n-1个盘子通过借助辅助塔(A塔)移到了C上;

代码实现
public class Hanoi
{
	public static void main(String[] args)
	{
		String from="A";
		String to="B";
		String help="C";
		printHanoiTower(3, from, to, help);
	}
	/**
	 * 
	 * @param N 初始的N个从小到大的盘子,N是最大编号
	 * @param from 原始柱子
	 * @param to  目标柱子
	 * @param help 辅助的柱子
	 */

/**
1-N从A移动到B,C作为辅助
    等价于:
        1、1~N-1从A移动到C,B为辅助
        2、把N从A移动到B
        3、1-N-1从C移动到B,A为辅助
*/
	static void printHanoiTower(int N,String from,String to,String help) {		
		if (N==1)
		{
			System.out.println("move"+N+" from"+from+" to"+to);
			return;
		}
		printHanoiTower(N-1, from, help, to);//先把N-1个盘子移动到辅助空间上去
		System.out.println("move"+N+" from"+from+" to"+to);//N可以顺利的到达target
		printHanoiTower(N-1, help, to, from);//让N-1从辅助空间回到源空间上去
	}
}

运行结果
move1 fromA toB
move2 fromA toC
move1 fromB toC
move3 fromA toB
move1 fromC toA
move2 fromC toB
move1 fromA toB

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sparky*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值