最大正方形
思想:一动态方程定义的是范围matrix(0, 0) 到 matrix(i, j)的最大正方形,但是找不到递推关系,
dp[i][j]应该表示以第i行第j列为右下角所能构成的最大正方形边长,并且这个min的意思比较难理解,可以自己手推一波理解一下。我的评价是这道题有点难想,尤其是min的设定。
public int maximalSquare(char[][] matrix) {
/**
dp[i][j]表示以第i行第j列为右下角所能构成的最大正方形边长, 则递推式为:
dp[i][j] = 1 + min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]);
**/
int[][] dp=new int[matrix.length][matrix[0].length];
int flag=0;
for(int j=0; j<matrix[0].length; j++) {
if(matrix[0][j] == '1'){dp[0][j]=1;flag=1;}
}
for(int i=0; i<matrix.length; i++) {
if(matrix[i][0] == '1'){dp[i][0]=1;flag=1;}
}
int max;
max= flag==1 ? 1:0;
for(int i=1; i<matrix.length; i++)
for(int j=1; j<matrix[0].length; j++) {
if(matrix[i][j]=='1') {
dp[i][j]=Math.min(dp[i-1][j], Math.min(dp[i-1][j-1], dp[i][j-1]))+1;
max=Math.max(max, dp[i][j]);
}
}
return (int) Math.pow(max, 2);
}
完全平方数
public int numSquares(int n) {
int[] dp=new int[n+1];
//初始化,dp是和为i的最小完全平方组合数,最坏的情况是和为i个1组成
for(int i=0; i<=n; i++)dp[i]=i;
for(int i=1; i<=n; i++) //内层循环的终止条件是j*j<=i
for(int j=1; j<=Math.sqrt(i); j++) {
//状态方程
dp[i]=Math.min(dp[i], dp[(int) (i-Math.pow(j, 2))]+1);
}
return dp[n];
}
个人觉得完全平方数和凑零钱有些像,但又不完全像
零钱兑换
public int coinChange(int[] coins, int amount) {
int max = amount + 1;
int[] dp = new int[amount + 1];
Arrays.fill(dp, max);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < coins.length; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}