价值:记录学习过程的思考,本身就是一场动态规划的前生,记忆化搜索。
Problem: leetcode.cn/problems/Il…
[TOC]
思路
dp重复子结构,简单想一下, dp[3][2] 会用到 dp[2][2]和dp[2][1] dp[3][3] 会用到 dp[2][2]和dp[2][3] 重复使用子结构dp[2][2],记忆化->改为dp 考虑右下边(的状态怎么算出来的) 每一步只能移动到下一行中相邻的结点上,状态转移(递推痕迹)
手推的过程,case不是给出的
元数据放到二维数组中
------> | | 方向
| i\j | j=0 | j=1 | j = 2 | j=3 |
|---|---|---|---|---|
| i=0 | 2 | 0 | 0 | 0 |
| i=1 | 3 | 4 | 0 | 0 |
| i=2 | 6 | 5 | 7 | 0 |
| i=3 | 4 | 1 | 8 | 3 |
要求的状态f[i][j]由 (左上 f(i-1,j-1) , 正上f(i-1,j))+ nums[i][j] 求的 计算包含当前值的dp,然后查找最后一行的dp,取min,因为不一定就包含
递推公式 :f -> dp : dp[i][j] = min(dp[i-1][j-1],dp[i-1][j]) + arr[i][j]
dp状态表,填表
init
先[0][j],
| i\j | j=0 | j=1 | j = 2 | j=3 |
|---|---|---|---|---|
| i=0 | 2 | 0 | 0 | 0 |
| i=1 | 0 | 0 | 0 | 0 |
| i=2 | 0 | 0 | 0 | 0 |
| i=3 | 0 | 0 | 0 | 0 |
再[i][0]
| i\j | j=0 | j=1 | j = 2 | j=3 |
|---|---|---|---|---|
| i=0 | 2 | 0 | 0 | 0 |
| i=1 | 5 | 0 | 0 | 0 |
| i=2 | 11 | 0 | 0 | 0 |
| i=3 | 15 | 0 | 0 | 0 |
依赖顺序,推出当前的值怎么算出来的,填状态进去dp表格
算出来的状态
| i\j | j=0 | j=1 | j = 2 | j=3 |
|---|---|---|---|---|
| i=0 | 2 | 0 | 0 | 0 |
| i=1 | 5 | 6 | 0 | 0 |
| i=2 | 11 | 10 | 13 | 0 |
| i=3 | 15 | 11 | 18 | 16 |
答案: 因为不一定包含最后这个字符,min(15,11,18,16) = 11
解题方法
描述你的解题方法
复杂度
时间复杂度:
添加时间复杂度, 示例:
空间复杂度:
添加空间复杂度, 示例:
Code
class Solution {
public int minimumTotal(List<List<Integer>> arr) {
//dp[i][j] = min(dp[i-1][j-1],dp[i-1][j]) + w[i][j]
//行~i:[0~i]
//列~j:[0~j]
int N = arr.size();
int[][] dp = new int[N][N];
dp[0][0] = arr.get(0).get(0);
for(int i = 1; i < N ; i++){
dp[i][0] = dp[i-1][0] + arr.get(i).get(0);
for(int j = 1; j < i; j++){
dp[i][j] = Math.min(dp[i-1][j-1], dp[i-1][j]) + arr.get(i).get(j);
}
dp[i][i] = dp[i-1][i-1] + arr.get(i).get(i);
}
int ans = dp[N-1][0];
for(int i =1; i < N; i++){
ans = Math.min(ans,dp[N-1][i]);
}
return ans;
}
}