9-1 什么是动态规划
记忆化搜索–自上而下的解决问题
动态规划–自下而上的解决问题
动态规划:将原问题拆解成若干子问题,同时保存子问题的答案,使得每个子问题只求解一次,最终获得原问题的答案。
递归问题--------重叠子问题
-
记忆化搜索--------自顶向下的解决问题
-
动态规划--------自底向上的解决问题
最优子结构:通过求子问题的最优解,可以获得原问题的最优解。
递归问题--------重叠子问题 + 最优子结构
-
记忆化搜索--------自顶向下的解决问题
-
动态规划--------自底向上的解决问题
题目: 斐波那契数列:指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368……
特别指出:第0项是0,第1项是第一个1。
这个数列从第三项开始,每一项都等于前两项之和。
public class Solution1 {
private int num = 0;
public int fib( int n ){
num ++;
if( n == 0 )
return 0;
if( n == 1 )
return 1;
return fib(n-1) + fib(n-2);
}
public int getNum(){
return num;
}
public static void main(String[] args) {
int n = 50;
Solution1 solution = new Solution1();
long startTime = System.currentTimeMillis();
int res = solution.fib(n);
long endTime = System.currentTimeMillis();
System.out.println("fib(" + n + ") = " + res);
System.out.println("time : " + (endTime - startTime) + " ms");
System.out.println("run function fib() " + solution.getNum() + " times.");
}
}
import java.util.Arrays;
public class Solution2 {
private int num = 0;
public int fib(int n){
int[] memo = new int[n + 1];
Arrays.fill(memo, -1);
return fib(n, memo);
}
private int fib(int n, int[] memo){
num ++;
if(n == 0)
return 0;
if(n == 1)
return 1;
if(memo[n] == -1)
memo[n] = fib(n - 1, memo) + fib(n - 2, memo);
return memo[n];
}
public int getNum(){
return num;
}
public static void main(String[] args) {
int n = 42;
Solution2 solution = new Solution2();
long startTime = System.currentTimeMillis();
int res = solution.fib(n);
long endTime = System.currentTimeMillis();
System.out.println("fib(" + n + ") = " + res);
System.out.println("time : " + (endTime - startTime) + " ms");
System.out.println("run function fib() " + solution.getNum() + " times.");
}
}
import java.util.Arrays;
public class Solution3 {
public int fib(int n){
int[] memo = new int[n + 1];
Arrays.fill(memo, -1);
memo[0] = 0;
memo[1] = 1;
for(int i = 2 ; i <= n ; i ++)
memo[i] = memo[i - 1] + memo[i - 2];
return memo[n];
}
public static void main(String[] args) {
int n = 1000;
Solution3 solution = new Solution3();
long startTime = System.currentTimeMillis();
int res = solution.fib(n);
long endTime = System.currentTimeMillis();
System.out.println("fib(" + n + ") = " + res);
System.out.println("time : " + (endTime - startTime) + " ms");
}
}
优化
public class Solution1 {
public int climbStairs(int n) {
if(n <= 0)
throw new IllegalArgumentException("n must be greater than zero");
if(n == 1)
return 1;
int prev = 1, cur = 1;
for(int i = 3 ; i <= n + 1; i ++){
int f = cur + prev;
prev = cur;
cur = f;
}
return cur;
}
public static void main(String[] args) {
System.out.println((new Solution1()).climbStairs(10));
}
}
public class Solution2 {
public int climbStairs(int n) {
if(n <= 0)
throw new IllegalArgumentException("n must be greater than zero");
if(n == 1)
return 1;
int[][] base = {{1, 1}, {1, 0}};
return matrix_pow(base, n)[0][0];
}
private int[][] matrix_pow(int[][] m, int n){
if(n == 1)
return m;
int[][] t = matrix_pow(m, n / 2);
int[][] res = matrix_multiply(t, t);
if(n % 2 == 1)
return matrix_multiply(res, m);
return res;
}
int[][] matrix_multiply(int[][] m1, int[][] m2){
int[][] res = new int[2][2];
res[0][0] = m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0];
res[0][1] = m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1];
res[1][0] = m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0];
res[1][1] = m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1];
return res;
}
public static void main(String[] args) {
System.out.println((new Solution2()).climbStairs(10));
}
}
public class Solution3 {
public int climbStairs(int n) {
if(n <= 0)
throw new IllegalArgumentException("n must be greater than zero");
if(n == 1)
return 1;
double sqrt5 = Math.sqrt(5.0);
return (int)((Math.pow((1 + sqrt5) / 2, n + 1) - Math.pow((1 - sqrt5) / 2, n + 1)) / sqrt5);
}
public static void main(String[] args) {
System.out.println((new Solution3()).climbStairs(10));
}
}