经典递归问题

本文探讨了经典的递归问题,包括取球问题、全排列、最大公共子序列、字符串翻转、排列组合等,并通过递归思路进行了解析。递归的核心在于找到问题的出口和基本情况,通过分解问题来逐步求解。例如,取球问题可以通过取到特殊球或未取到特殊球两种情况递归求解。同时,文章也提到了汉诺塔游戏的递归解决方案,强调理解递归执行过程的重要性。
摘要由CSDN通过智能技术生成

 经典递归问题

1.取球问题:在n个球中,任意取m个(不放回),求有多少种不同取法。

  • 对于递归问题来说,该题似乎没有突破口,那么就需要发挥想象。
  • 带入一组简单的数字,比如3个中取2个球,将所有可能的组合枚举出来,观察这些组合可以如何划分。比如abc三个球,有ab,ac,bc三种,可以想象n个球中取1个幸运球,那么要么取到该球,要么取不到。
  • 如果取到了这个特殊球, 则:f(n-1,m-1),总数总是要减1, 因为取到了特殊球, 所以m-1, 反之没有取到特殊球, 则 f(n-1,m) 总数还是减1, 但是m的值不变。此时,所有取法即为f(n-1,m-1)+f(n-1,m)
  • 递归的形式出来之后,就需要考虑出口问题。
import java.util.Scanner;

public class Main {
	public static int f(int n, int m) {
		//出口判断
		if (n < m)//不可能取到
			return 0;
		if (n == m)
			return 1;
		if (m == 0)//这个不能落下,否则会栈溢出;判断是否取到最后
			return 1;
		return f(n - 1, m - 1) + f(n - 1, m);
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = f(n, m);
		System.out.println(k);
	}
}

 2.求n个元素的全排列

//求n个元素的全排列
public class Main {
	// 将每一个元素放到第1个位置(需要进行回溯,不能覆盖掉任何一个元素),再将后面的元素进行全排列
	// 递归方法来打印不需要返回什么,void
	public static void f(char[] data, int k) {
		//递归的出口,如果关注点到了最后一个位置就需要打印了
		if (k == data.length) {
			for (int i = 0; i < data.length; i++) {
				System.out.print(data[i] + " ");
			}
		
车厢调度问题是一个经典递归问题,其实质是求解给定一列车厢,将其从出发状态调度到目标状态的所有可能调度方案。 具体来说,我们可以将车厢调度问题转化为以下问题:给定一个初始状态和目标状态,每次可以将初始状态中最上面的车厢移动到一个辅助轨道中,或从辅助轨道中移回一个车厢放到初始状态中的某个位置。求解从初始状态到目标状态的所有可能方案。 递归求解车厢调度问题的思路如下: 1. 如果初始状态和目标状态相同,那么这个问题已经被解决了,直接返回即可。 2. 否则,我们可以将初始状态中最上面的车厢移动到辅助轨道中,并递归求解从剩余的车厢和辅助轨道到达目标状态的所有可能方案。 3. 接着,我们将辅助轨道中最上面的车厢移回初始状态的某个位置,并递归求解从剩余的车厢和辅助轨道到达目标状态的所有可能方案。 4. 重复步骤 2 和 3,直到所有可能的方案都被考虑过。 需要注意的是,在递归求解车厢调度问题时,我们需要记录当前的状态以及已经移动到辅助轨道中的车厢,以便在移回车厢时能够正确地还原状态。此外,为了避免重复计算,我们可以使用记忆化搜索技术,对已经求解过的状态进行缓存,以便下次直接返回结果。 总之,递归求解车厢调度问题需要注意细节,但其思路相对简单清晰,是一个很好的经典递归问题
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值