练习一 : 解码方法

java
class Solution {
public int numDecodings(String s) {
int len = s.length();
char[] ch = s.toCharArray();
int [] arr = new int[len];
for(int i = 0;i<len;i++){
arr[i] = ch[i]-'0';
}
if(arr[0] == 0){
return 0;
}
int[] dp = new int [len+1];
dp[0] = 1;//将第一位为0过滤掉了
if(len == 1){
return dp[0];
}
int two = arr[0]*10+arr[1];
if(arr[1] == 0){
// 0 不能单独解码,只能看是否是 10/20
dp[1] = (two == 10 || two == 20) ? 1 : 0;
}else if(two > 26){
dp[1] = 1;
}else{
dp[1] = 2;
}
if(len == 2){
return dp[1];
}
for(int i = 2;i<len;i++){
int now = arr[i];
int preTwo = arr[i-1]*10 + now;
if(dp[i-1] == 0&&dp[i-2] == 0){
return 0;
}
if(now == 0){//单独解码失败
// 当前是0,必须和前一位组合 10/20,否则无解
if(preTwo !=10 && preTwo!=20){
return 0;
}
dp[i] = dp[i-2];
}
else if(preTwo <10 || preTwo>26){
// 不能组合,只能单独解码
dp[i] = dp[i-1];
}
else{
// 既能单独又能组合
dp[i] = dp[i-1]+dp[i-2];
}
}
return dp[len-1];
}
}
算法原理 :
状态表示 : dp[i] : 解码到 i 位置的解码方法数 ;
状态转移方程 : dp[i] : 可以在 dp[i-1] 方法数的基础上从 i 位置解码 , 解码一个字符 ; 也可以在 dp[i-2] 方法数的基础上从 i-1 位置解码 , 解码两个字符

细节问题 :


代码细节 :
- 预处理字符串 , 先将字符串拆分为字符数组 , 再将字符数组转为整型数组 , 方便计算
- 边界判断 , 重点预处理前两个字符
- 重点 : 动态规划
练习二 : 不同路径 1

java
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m+1][n+1];
dp[1][0] = 1;
for(int i = 1;i<=m;i++){
for(int j = 1;j<=n;j++){
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
return dp[m][n];
}
}
算法原理 :
dp[i][j] : 到达 i,j 位置的路径数
由于到达 [i,j] 位置 可以从 [i-1,j] ,或者从 [i,j-1] 走一步到达 ; 所以dp[i][j] = dp[i-1][j]+dp[i][j-1]
初始化问题 : 防止下标越界 , 可以在数组初始化时多加一行一列 , 将第 0 行和第 0 列分别初始化 , 为了不影响最终结果 , 只将 dp[1][0] 初始化为 1 , 其余为 0
返回值问题 : 由于多加一行一列 , dp 数组中的 [i,j] 映射到原路径中应该是 [i-1,j-1] ; 所以最终返回的位置是原路径中的 [m-1,n-1] , 对应到 dp 数组中就是 dp[m][n]
练习三 : 不同路径2

java
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length;//行数
int n = obstacleGrid[0].length;//列数
int[][] dp = new int[m+1][n+1];
dp[0][1] = 1;
for(int i = 1;i<=m;i++){
for(int j = 1;j<=n;j++){
if(obstacleGrid[i-1][j-1] == 1){
dp[i][j] = 0;
}else{
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
}
return dp[m][n];
}
}
算法原理 :
大体思路同上题 ,
细节 : 有障碍物时 : dp[i][j] = 0 ; 无障碍物时 : dp[i][j] = dp[i-1][j]+dp[i][j-1]
练习四 : 下降路径最小和

java
class Solution {
public int minFallingPathSum(int[][] matrix) {
int m = matrix.length;//行数
int n = matrix[0].length;//列数
int[][] dp = new int[m+1][n+2];
for(int i = 1;i<=m;i++){
dp[i][0] = dp[i][n+1] = Integer.MAX_VALUE;
}
for(int i =1;i<=m;i++){
for(int j = 1;j<=n;j++){
dp[i][j] = Math.min(dp[i-1][j],Math.min(dp[i-1][j-1],dp[i-1][j+1]))+matrix[i-1][j-1];
}
}
int ret = Integer.MAX_VALUE;
for(int i = 1;i<=n;i++){
ret = Math.min(ret,dp[m][i]);
}
return ret;
}
}
算法原理 :
dp[i][j] : 到达 [i,j] 位置的最小下降路径

返回值 : 需要遍历最后一行