70.Climbing Stairs
题目链接:https://leetcode.com/problems/climbing-stairs/description/
题目大意:爬楼梯问题,一共花费n步爬到楼顶,一次可以爬一个台阶或两个台阶,求出一共有多少种方法可以爬到楼顶。
此题其实是裴波那挈数列问题。
法一:动规公式:fib[n] = fib[n - 1] + fib[n - 2]。用for循环数组来求fib[n],将其返回既是结果。代码如下(耗时0ms):
1 public int climbStairs(int n) { 2 int[] fib = new int[1000]; 3 fib[0] = 1; 4 fib[1] = 1; 5 fib[2] = 2; 6 for(int i = 3; i <= n; i++) { 7 fib[i] = fib[i - 1] + fib[i - 2]; 8 } 9 return fib[n]; 10 }
法二(超时):直接递归,超时了,而且递归栈的深度也是一个问题。代码如下:
1 public int climbStairs(int n) { 2 if(n == 0 || n == 1) { 3 return 1; 4 } 5 else if(n == 2) { 6 return 2; 7 } 8 return climbStairs(n - 1) + climbStairs(n - 2); 9 }
法三(借鉴):其实是法二的改进版,记忆性递归,用数组记录已经计算过的fib[i],如果已经计算过则直接返回不用再继续递归。代码如下(耗时0ms):
1 public int climbStairs(int n) { 2 int[] fib = new int[1000]; 3 for(int i = 0; i <= n; i++) { 4 fib[i] = 0; 5 } 6 return fib(fib, n); 7 } 8 9 public int fib(int[] fib, int n) { 10 if(n == 0 || n == 1) { 11 return 1; 12 } 13 else if(n == 2) { 14 return 2; 15 } 16 if(fib[n] != 0) { 17 return fib[n]; 18 } 19 else { 20 fib[n] = fib(fib, n - 1) + fib(fib, n - 2); 21 return fib[n]; 22 } 23 }
快速幂知识点:
快速幂:http://www.cnblogs.com/CXCXCXC/p/4641812.html
快速幂取模:http://www.cnblogs.com/lj-1568/p/4754336.html
借鉴: http://blog.csdn.net/hanleijun/article/details/24550065
https://leetcode.com/problems/climbing-stairs/solution/
1 package problem_70; 2 3 public class MatrixTest { 4 5 static int[][] matrix; 6 7 public static void main(String[] args) { 8 init(2); 9 matrix[0][0] = 1; 10 matrix[0][1] = 1; 11 matrix[1][0] = 1; 12 matrix[1][1] = 0; 13 int[][] temp = new int[matrix.length][matrix.length]; 14 temp = pow(4); 15 for (int[] a : temp) { 16 for (int b : a) { 17 System.out.print(b + " "); 18 } 19 System.out.println(); 20 } 21 System.out.println("斐波那契数列的fn值为:" + temp[0][1]); 22 } 23 24 //初始化矩阵 25 public static void init(int n) { 26 matrix = new int[n][n]; 27 } 28 29 //矩阵相乘 30 public static int[][] matrixMulti(int[][] m, int[][] n) { 31 int[][] temp = new int[matrix.length][matrix.length]; 32 for (int k = 0; k < matrix.length; k++) { 33 for (int i = 0; i < matrix.length; i++) { 34 for (int j = 0; j < matrix.length; j++) { 35 temp[k][i] += m[k][j] * n[j][i]; 36 } 37 } 38 } 39 return temp; 40 } 41 42 //矩阵快速幂 43 public static int[][] pow(int n) { 44 int[][] temp = new int[matrix.length][matrix.length]; 45 if (n == 1) { 46 return matrix; 47 } else { 48 if (n % 2 != 0) { //奇数 49 temp = pow((n - 1) / 2); 50 temp = matrixMulti(temp, temp); 51 return matrixMulti(temp, matrix); 52 } else { //偶数 53 temp = pow(n / 2); 54 temp = matrixMulti(temp, temp); 55 return temp; 56 } 57 } 58 } 59 }
法四(借鉴):数学方法
1 public class Solution { 2 public int climbStairs(int n) { 3 double sqrt5=Math.sqrt(5); 4 double fibn=Math.pow((1+sqrt5)/2,n+1)-Math.pow((1-sqrt5)/2,n+1); 5 return (int)(fibn/sqrt5); 6 } 7 }