1.62. 不同路径
思路:看到向右向下就可以用动态规划的方法,考虑边界,再找到递推公式。优化的话,可以将二维数组转化为一位数组。
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
//第一列都是1
for (int i = 0; i < m; i++) {
dp[i][0] = 1;
}
//第一行都是1
for (int i = 0; i < n; i++) {
dp[0][i] = 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 - 1][n - 1];
}
class Solution {
public int uniquePaths(int m, int n) {
int[] dp = new int[m];
Arrays.fill(dp,1);
for(int j=1;j<n;j++)
for(int i=1;i<m;i++)
dp[i] = dp[i]+dp[i-1];
return dp[m-1];
}
}
2.剑指 Offer 47. 礼物的最大价值
动态规划:
①边界考虑
- 如果在i=0,j=0处,dp[i][j]=grid[i][j]
- 如果在最上面,则为第一行元素,那就只能让行元素累加
- 如果在最左边,那就上列元素累加
- 如果都不在,那就让礼物价值的点加上二者的最大值
②转移方程
dp[i][j]=max(dp[i-1][j],dp[i][j-1])+grid[i][j];
class Solution {
public int maxValue(int[][] grid) {
if(grid==null || grid.length==0)
return 0;
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
dp[0][0] = grid[0][0];
for(int i=1;i<n;i++){
dp[0][i] = grid[0][i] + dp[0][i-1];
}
for(int i=1;i<m;i++){
dp[i][0] = grid[i][0] + dp[i-1][0];
}
for(int i=1;i<m;i++)
for(int j=1;j<n;j++)
dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]) + grid[i][j];
return dp[m-1][n-1];
}
}
//边界判断
if(grid==null||grid.length==0)
return 0;
int m=grid.length;
int n=grid[0].length;
//初始化dp的最上面一行,从左到右累加
for(int i=1;i<n;i++){
grid[0][i] = grid[0][i]+grid[0][i-1];
}
//初始化dp的最左边一列,从上到下累加
for(int i=1;i<m;i++){
grid[i][0] = grid[i][0]+grid[i-1][0];
}
//递推公式
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
grid[i][j] = grid[i][j] + Math.max(grid[i][j-1],gridi-1][j]);
}
}
return grid[m-1][n-1];
3.647. 回文子串
动态规划:
//字符串的长度
int length=s.length();
boolean[] dp = new boolean[length];
int count = 0;
for(int j=0;j<length;j++){
for(int i=0;i<=j;i++){
if(s.charAt(i) == s.charAt(j) && (j-i<=2 || dp[i+1])){
dp[i]=true;
count ++;
}else{
dp[i] = false;
}
}
}
return count;
中心扩散法:
int length = s.length();
int size = 2 * length-1;
int count = 0;
for(int i=0;i<size;i++){
int left = i/2;
int right = left + i%2;
while(left>=0&&right<length&&s.charAt(left)==s.charAt(right)){
left--;
right++;
count++;
}
}
return count;
4.1277. 统计全为 1 的正方形子矩阵
class Solution {
public int countSquares(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int[][] dp = new int[m][n];
int ans = 0;
// 预处理每一行和每一列
for (int i = 0; i < m; i++) {
ans += dp[i][0] = matrix[i][0];
}
for (int j = 0; j < n; j++) {
ans += dp[0][j] = matrix[0][j];
}
// 上述过程(0, 0)判断了两次, 如果matrix[0][0] == 1,说明ans多算了一个
if (matrix[0][0] == 1) {
ans--;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == 1) {
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
ans += dp[i][j];
}
}
}
return ans;
}
}
54.221. 最大正方形
class Solution {
public int maximalSquare(char[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int[][] dp = new int[m+1][n+1];
int maxside = 0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(matrix[i-1][j-1]=='1'){
dp[i][j] = Math.min(dp[i-1][j],Math.min(dp[i-1][j-1],dp[i][j-1]))+1;
maxside = Math.max(maxside,dp[i][j]);
}
}
}
return maxside * maxside;
}
}