爬楼梯问题解法

package com.example.demo.leetcode.recursive;

/**
 * @author wangli66
 * @describtion 爬楼梯问题解决
 * 问题:
 * 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
 * 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
 * 注意:给定 n 是一个正整数。
 * 示例 1:
 * 输入: 2
 * 输出: 2
 * 解释: 有两种方法可以爬到楼顶。
 * 1.  1 阶 + 1 阶
 * 2.  2 阶
 * 示例 2:
 * 输入: 3
 * 输出: 3
 * 解释: 有三种方法可以爬到楼顶。
 * 1.  1 阶 + 1 阶 + 1 阶
 * 2.  1 阶 + 2 阶
 * 3.  2 阶 + 1 阶
 * 来源:https://leetcode-cn.com/explore/featured/card/recursion-i/258/memorization/1214/
 *
 *     解决方案
 *     方法 1:暴力法
 *     方法 2:记忆化递归
 *     方法 3:动态规划
 *     方法 4: 斐波那契数
 *     方法 5: Binets 方法
 *     方法 6: 斐波那契公式
 * @create-time 10:10 2020/4/7
 ***************************************************/
public class ClimbStairsTest {

    public static void main(String[] args) {
        System.out.println(solution1(4));
    }
    /**
     * @Description: 方法 1:暴力法
     * @param: [n]
     * @return: int
     * @Date: 2020/4/7
     */
    public static int solution1(int n) {
        return climbStairs1(0,n);
    }

    private static int climbStairs1(int i, int n) {
        if(i > n) {
            return 0;
        }
        if(i == n) {
            return 1;
        }
        return climbStairs1(i+1,n) + climbStairs1(i+2, n);
    }

    /**
     * @Description: 方法 2:记忆化递归
     * @param: [n]
     * @return: int
     * @Date: 2020/4/7
     */
    public static int solution2(int n) {
        int[] cache = new int[n+1];
        return climbStairs2(0,n,cache);
    }

    private static int climbStairs2(int i, int n, int[] cache) {
        if(i>n) {
            return 0;
        }
        if(i == n) {
            return 1;
        }
        cache[i] = climbStairs2(i+1 , n, cache) + climbStairs2(i+2, n ,cache);
        return cache[i];
    }

    /**
     * @Description: 方法 3:动态规划
     * @param: [n]
     * @return: int
     * @Date: 2020/4/7
     */
    public static int solution3(int n) {
        if(n == 1) {
            return 1;
        }
        int[] dp = new int[n+1];
        dp[1] = 1;
        dp[2] = 2;
        for(int i =3;i<n;i++) {
            dp[i] = dp[i-1]+dp[i-2];
        }
        return dp[n];
    }

    /**
     * @Description: 方法 4: 斐波那契数
     * @param: [n]
     * @return: int
     * @Date: 2020/4/7
     */
    public static int solution4(int n) {
        if(n == 1) {
            return 1;
        }
        int first = 1;
        int second = 2;
        for(int i=3;i<n;i++) {
            int third = first + second;
            first = second;
            second = third;
        }
        return second;
    }

    /**
     * @Description: 方法 5: Binets 方法
     * @param: [n]
     * @return: int
     * @Date: 2020/4/7
     */
    public static int solution5(int n) {
        int[][] q = {{1, 1}, {1, 0}};
        int[][] res = pow(q, n);
        return res[0][0];
    }

    public static int[][] pow(int[][] a, int n) {
        int[][] ret = {{1, 0}, {0, 1}};
        while (n > 0) {
            if ((n & 1) == 1) {
                ret = multiply(ret, a);
            }
            n >>= 1;
            a = multiply(a, a);
        }
        return ret;
    }
    public static int[][] multiply(int[][] a, int[][] b) {
        int[][] c = new int[2][2];
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
            }
        }
        return c;
    }

    /**
     * @Description: 方法 6: 斐波那契公式
     * @param: [n]
     * @return: int
     * @Date: 2020/4/7
     */
    public static int solution6(int n) {
        double sqrt = Math.sqrt(5);
        double pow = Math.pow((1+sqrt)/2,n+1) - Math.pow((1-sqrt)/2,n+1);
        return (int)(pow/sqrt);
    }
}

猜你喜欢

转载自www.cnblogs.com/chujian007/p/12653287.html