【NOTE】有关递归的题目——持续更新

递归

什么情况下可以考虑使用递归?

  1. 大问题可以分解成更小的子问题(递)
  2. 小问题和大问题求解方式一致,只是数据规模不一样
  3. 大问题最终可以分解成基本问题,基本问题可以直接求解
  4. 子问题的解汇集起来可以得到大问题的解(归)

递归两个基本要素

  1. 边界公式
  2. 递推公式

总结

核心:分而治之,减小问题规模

⚠️注意:一定要有递归出口

递归的弊端:重复计算(例如在不死神兔问题中)
递归的很多问题也可以转化成循环来做

题目

  1. 求阶乘
  2. 不死神兔—斐波那契
  3. 猴子吃桃
  4. 求0—7所能组成的奇数个数
  5. 上楼梯问题
  6. 直线分割平面问题
  7. 汉诺塔问题 ----6.16更新~
  8. 反转单链表

  1. 一个楼梯有n (n >= 1)级,每次走1级或两级,请问从1级台阶走到第n级台阶一共有多少种走法(假设一开始站在第0级台阶上)

思路:
【NOTE】有关递归的题目——持续更新_第1张图片
代码:

public class RecursionStair {

    public static void main(String[] args) {
		stair(n); 
    }

    //上n阶台阶,返回方法数量
    public static int stair(int n){
        if(n<1){
            return -1;
        }
        if(n==1){
            return 1;
        }
        if(n==2){
            return 2;
        }
        return stair(n-1)+stair(n-2);
    }

}

本题其他做法:

// 当n超过100时,会返回负值, int类型已经不能表示了……
//1.========数组的方法========
 public static long stair(int n){
        if(n==1) return 1;
        if(n==2) return 2;
        long[] arr = new long[n];
        arr[0]=1;
        arr[1]=2;
        for (int i = 2; i <n ; i++) {
            arr[i] = arr[i-1]+arr[i-2];
        }
        return arr[n-1];
    }
//2.=======动态规划,在力扣上看到大佬做的=====
// 利用一个temp存入 当n-1时的值+当n-2时的值
// = = 用递归的话,重复计算太多,无法通过
public static int solution(int n ){
        if(n<=2) return n;
        int p =1;
        int q =2;
        for (int i = 3; i <= n ; i++) {
            int temp = p+q;
            p = q;
            q = temp;
        }
        return q;
    }
  1. 计算n条直线最多能把平面分成多少部分? n>=1)
    这题还可以看一下:折线分割平面
    【递推】直线、折线、曲线分割平面、平面分割空间

以下是本人愚钝的思路:

代码:

/**
 * 题目:计算n条直线最多能把平面分成多少部分? n>=1
 * 题目条件是最多,故n>=2后新加的线必须与原有每条线都相交且交点不能重合
 * f(1)=2;
 * f(2)=4;
 * ...
 * f(n)=f(n-1)+(n-1)-1+2
 *     =f(n-1)+n
 *   (n-1)-1+2  -> 表示 第n条线加入后被分成(n-1)-1条线段和2条射线->将原有区域一分为二
*/
import java.util.Scanner;
public class PlanePart {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("请问您想用几条线将平面分割呢?");
        int line = scan.nextInt();
        System.out.println("Method 1:");
        System.out.println(partNumber(line));
        System.out.println("Method 2:");
        System.out.println(partNumber1(line));
    }

    //======数学方法======
    // n -> numbers of line
    public static int partNumber(int n ){
        if(n<1){
            return -1;
        }
        return n*(n+1)/2+1;
    }

    //===== Recursion =======
    public static int partNumber1(int n){
        if(n<1){
            return -1;
        }
        if(n==1){
            return 2;
        }
        return partNumber1(n-1)+n;
    }
}
  1. 汉诺塔问题
    有很多文章介绍了……递归的经典题!
    hhh 很多人都说不要去管递归的一步一步具体是怎么实现的,要抓住核心! 减小问题规模!
    关于这个题,我觉得……其实去玩一玩汉诺塔游戏真的可以帮助理解一下……
    = = 我就是玩了大概一小时,然后可以稍稍体会到:先把n-1个盘子挪到辅助杆 -> 把第n个(即最底部的)盘子挪到目标杆 -> 把n-1个盘子挪到目标杆 | 这么一个过程……当你完成第一步后,其实最初最底下的盘子当作消失了,重新定义哪个是“起始、辅助、目标”,然后n-1个盘子只是重复第一步过程……
public class HanoiProblem {
    public static void main(String[] args) {
        hanoi('A','C','B',3);
    }
    //start 起始杆名称
    //end  目标杆名称
    //middle 辅助杆名称
    // n 盘子数量
    // = = 注意变量名的顺序,起始、目标、辅助
    public static void  hanoi(char start, char end ,char middle, int n){
        if(n==1){
            System.out.println(start+"-->"+end);
            return;
        }
		// first step 把n-1个盘子从start杆挪到 middle杆
        hanoi(start,middle,end,n-1);
        //最底部的n从start杆挪到end杆
        System.out.println(start+"-->"+end);
        //最后middle杆为起始,end依然是目标,但此时start成为了辅助杆
        hanoi(middle,end,start,n-1);
    }
}

结果:

A–>C
A–>B
C–>B
A–>C
B–>A
B–>C
A–>C

  1. 反转单链表(待更新)

你可能感兴趣的:(递归)