zoukankan      html  css  js  c++  java
  • 青蛙跳台阶的相关问题

    青蛙跳台阶的相关问题

    问题一:青蛙一次只能跳 1 个台阶或者 2 个台阶, 计算从 0 台阶跳到 n 台阶有多少跳法,也就是的路径种类总和。

    import java.util.HashMap;
    
    public class StepJump {
        // 当青蛙只能跳 1 个台阶或者 2 个台阶, 计算从 0 台阶跳到 n 台阶的路径种类总和
        // 这个类似斐波那契数列 1 1 2 3 5 8 13
        // f(0)=1, f(1)=1, f(2)=f(0)+f(1),[其中f(0)表示从0阶直接跳到2阶] f(3)=f(1)+f(2)
        // f(3)=f(1)+f(2)的解释:[先跳到1阶的路径种类(然后直接跳到3阶)+先跳到2阶的路径种类(然后直接跳到3阶)]
        private static int fun1(int n) {
            if(n < 2)
                return 1;
            // [先跳到n-1阶的路径种类(然后直接跳到n阶)+先跳到n-2阶的路径种类(然后直接跳到n阶)]
            return fun1(n-1)+fun1(n-2); // 递归
        }
        // 避免重复计算,可用一个 HashMap 存储计算过的值,防止重复计算。
        private static int fun2(int n, HashMap<Integer, Integer> map) {
            if(n < 2)
                return 1;
            // 如果map包含 n 对应的值,直接返回
            if(map.containsKey(n))
                return map.get(n);
            // 递归求值,和fun1()同样道理
            int first = fun2(n-1, map);
            int second = fun2(n-2, map);
            int sum = first + second;
            // 储存值,方便下次寻找
            map.put(n, sum);
            return sum;
        }
        // 利用循环计算,效率更高
        private static int fun3(int n) {
            if(n < 2)
                return 1;
            int first = 1, second = 1, sum = 0;
            while(n-- >= 2) {
                sum = first + second;
                first = second;
                second = sum;
            }
            return sum;
        }
        public static void main(String[] args) {
            int  n = 40;
            long time = System.nanoTime();
            System.out.println(fun1(n));
            System.out.println("递归时间:" + (System.nanoTime() - time));
            time = System.nanoTime();
            System.out.println(fun2(n, new HashMap<Integer, Integer>()));
            System.out.println("HashMap时间:" + (System.nanoTime() - time));
            time = System.nanoTime();
            System.out.println(fun3(n));
            System.out.println("循环时间:" + (System.nanoTime() - time));
        }
    }
    /* Code Running Results:(每次结果可能不同)
     * 165580141
     * 递归时间:347549100
     * 165580141
     * HashMap时间:114000
     * 165580141
     * 循环时间:21000
     */
    

    问题二:青蛙一次能跳 1 到 n 个台阶, 计算从 0 台阶跳到 n 台阶有多少跳法,也就是的路径种类总和。

    public class StepJumpTwo {
        // 青蛙一次能跳 1 到 n 个台阶, 计算从 0 台阶跳到 n 台阶的路径种类总和
        // f(n)  = f(n-1)+f(n-2)+......+f(1)+f(0)------a式子
        // f(n-1)= f(n-2)+f(n-3)+......+f(1)+f(0)------b式子
        // (a式子)-(b式子)得  f(n)-f(n-1)=f(n-1)
        // 最终得到 f(n)=2*f(n-1)的等比数列,该等比数列为2^(n-1)
        private static int fun(int n){
            if(n < 2)
                return 1;
            return 1<<(n-1);  // 位运算,速度更快
        }
        public static void main(String [] args){
            System.out.println(fun(10));
        }
    }
    /* Code Running Results:
     * 512
     */
    

    问题三:青蛙一次能跳 1 到 m 个台阶, 计算从 0 台阶跳到 n 台阶有多少跳法,也就是的路径种类总和。

    public class StepJumpThree {
        // 青蛙一次能跳 1 到 m 个台阶, 计算从 0 台阶跳到 n 台阶的路径种类总和
    
        // 情况1 n <= m 时,也就回到了问题二 f(n)=2*f(n-1), 等比数列为2^(n-1)
    
        // 情况2 当 n-1 = m 时
        // f(n)  = f(n-1)+f(n-2)+......+f(2)+f(1) 接下所有的计算又回到情况1
        //       = 2*f(n-2)+2*f(n-3)+......+2*f(1)+f(1)
        //       = ......
        //       = 2^(n-1)-1 (f(n)=2*f(n-1)的等比数列[2^(n-1)]的前 n-1 项和[2^(n-1)-1]
    
        // 情况3 当 n-1 > m 时
        // f(n)  = f(n-1)+f(n-2)+......+f(n-m+1)+f(n-m)------a式子
        // f(n-1)= f(n-2)+f(n-3)+......+f(n-m)+f(n-1-m)------b式子
        // (a式子)-(b式子)得  f(n)-f(n-1)=f(n-1)-f(n-1-m)
        // 最终得到 f(n)=2*f(n-1)-f(n-1-m)
    
        private static int fun(int n, int m){
           if(n < 2)
               return 1;
           if(n <= m)     // 情况1
               return 1<<(n-1);
           if(n-1 == m)   // 情况2
               return (1<<(n-1))-1;
            // 情况3
           return 2*fun(n-1, m)+fun(n-1-m, m);
        }
        public static void main(String [] args){
            System.out.println(fun(1, 5));  // n < 2
            System.out.println(fun(4, 5));  // 情况1
            System.out.println(fun(6, 5));  // 情况2
            System.out.println(fun(7, 5));  // 情况3
        }
    }
    /* Code Running Results:
     * 1
     * 8
     * 31
     * 63
     */
    
  • 相关阅读:
    数组静态初始化和动态初始化
    一维数组
    标识符啊
    常量定义
    11.08问题总结
    毕设(10.30)
    毕设(10.29)
    毕设(10.28)
    毕设(10.27)
    毕设(10.26)
  • 原文地址:https://www.cnblogs.com/jiaohuadehulike/p/14295003.html
Copyright © 2011-2022 走看看