引入
斐波拉契数列
暴力搜索
static int fib(int n) {if (n == 1 || n == 2) return 1;return fib(n - 1) + fib(n - 2);}
记忆化搜索(备忘录)
自上而下的解决问题
static int[] memo = new int[100];static int fib2(int n) {if (n == 1 || n == 2) return 1;if (memo[n] == 0)memo[n] = fib2(n - 1) + fib2(n - 2);return memo[n];}
动态规划
自下而上的解决问题
static int fib3(int n) {int[] memo = new int[100];memo[0] = 0;memo[1] = 1;for (int i = 2; i <= n; i++)memo[i] = memo[i - 1] + memo[i - 2];return memo[n];}

习题
leetcode120
基本思路
class Solution {public int minimumTotal(List<List<Integer>> triangle) {int n = triangle.size();int[][] dp = new int[n][n];for (int i = n - 1; i >= 0; i--) {for (int j = 0; j < triangle.get(i).size(); j++) {if (i == n - 1) {dp[i][j] = triangle.get(i).get(j);}elsedp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle.get(i).get(j);}}return dp[0][0];}}
优化,增加一行数组避免判断,由于每一层状态只与下一层有关,优化一维空间。
class Solution {public int minimumTotal(List<List<Integer>> triangle) {int n = triangle.size();int[] dp = new int[n + 1];for (int i = n - 1; i >= 0; i--) {for (int j = 0; j < triangle.get(i).size(); j++) {dp[j] = Math.min(dp[j], dp[j + 1]) + triangle.get(i).get(j);}}return dp[0];}}
递归1
class Solution {int res = Integer.MAX_VALUE;public int minPathSum(int[][] grid) {dfs(grid, 0, 0, grid[0][0]);return res;}void dfs(int[][] g, int x, int y, int cur) {if (x == g.length - 1 && y == g[0].length - 1) {res = Math.min(res, cur);return;}if (y + 1 < g[0].length)dfs(g, x, y + 1, cur + g[x][y + 1]);if (x + 1 < g.length)dfs(g, x + 1, y, cur + g[x + 1][y]);}}
递归2+备忘录
class Solution {int[][] memo = new int[210][210];public int minPathSum(int[][] grid) {for (int i = 0; i < memo.length; i++)Arrays.fill(memo[i], -1);return dfs(grid, 0, 0);}// 从x y位置到终点的最小总和 cur为已消耗int dfs(int[][] g, int x, int y) {if (x == g.length || y == g[0].length) return Integer.MAX_VALUE;if (x == g.length - 1 && y == g[0].length - 1) {return g[x][y];}if (memo[x][y] != -1)return memo[x][y];memo[x][y] = Math.min(dfs(g, x + 1, y), dfs(g, x, y + 1)) + g[x][y];return memo[x][y];}}
动态规划
class Solution {
public int minPathSum(int[][] grid) {
int n = grid.length;
if (n == 0) return 0;
int m = grid[0].length;
int[][] dp = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (i == 0 && j == 0)
dp[i][j] = grid[i][j];
else if (i == 0)
dp[i][j] = grid[i][j] + dp[i][j - 1];
else if (j == 0)
dp[i][j] = grid[i][j] + dp[i - 1][j];
else
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[n - 1][m - 1];
}
}
