劍指 Offer II 100. 三角形中最小路徑之和
優(yōu)化路徑,建立表達式子 dp[i+1][j]=Math.min(dp[i][j]+tmp1,dp[i+1][j]);
dp[i+1][j+1]=Math.min(dp[i][j]+tmp2,dp[i+1][j+1]);
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
// 動態(tài)規(guī)劃
int m=triangle.size();int n=triangle.get(m-1).size();
int[][] dp=new int[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
dp[i][j]=Integer.MAX_VALUE;
}
}
dp[0][0]=triangle.get(0).get(0);
for(int i=0;i<m-1;i++){
for(int j=0;j<i+1;j++){
int tmp1=triangle.get(i+1).get(j);
int tmp2=triangle.get(i+1).get(j+1);
dp[i+1][j]=Math.min(dp[i][j]+tmp1,dp[i+1][j]);
dp[i+1][j+1]=Math.min(dp[i][j]+tmp2,dp[i+1][j+1]);
}
}
int min=dp[m-1][0];
for(int i=0;i<m;i++){
// System.out.println(dp[m-1][i]);
min=Math.min(dp[m-1][i],min);
}
return min;
}
}
#### [劍指 Offer II 103\. 最少的硬幣數(shù)目](https://leetcode.cn/problems/gaM7Ch/)
把amount進行劃分,建立dp數(shù)組,數(shù)組的下標對應硬幣的個數(shù),動態(tài)規(guī)劃方程
dp[i]=Math.min(dp[i-coins[j]+1,dp[i]),
初始dp[0]=0,其余數(shù)值是amount+1,
最后進行判定能否dp[amout]>amount?amount:dp[amount];
class Solution {
public int coinChange(int[] coins, int amount) {
int n=coins.length;
Arrays.sort(coins);
if(amount==0){
return 0;
}
int[] dp=new int[amount+1];
Arrays.fill(dp,amount+1);
dp[0]=0;
for(int i=1;i<amount+1;i++){
for(int j=n-1;j>=0;j--){
if(coins[j]<=i){
dp[i]=Math.min(dp[i-coins[j]]+1,dp[i]);
}
}
}
return dp[amount]>amount?-1:dp[amount];
}
}
劍指 Offer II 104. 排列的數(shù)目
和上面的一樣,拆分成背包,然后構造動態(tài)規(guī)劃方程。
dp[i]+=dp[i-num];
class Solution {
public int combinationSum4(int[] nums, int target) {
// 動態(tài)規(guī)劃和深度優(yōu)先遍歷
Arrays.sort(nums);
int n=nums.length;
int[] dp=new int[target+1];
dp[0]=1;
for(int i=1;i<target+1;i++){
for(int num:nums){
if(i>=num){
dp[i]+=dp[i-num];
}
}
}
return dp[target];
}
}
劍指 Offer II 107. 矩陣中的距離
對于矩陣中的任意一個 11 以及一個 00,我們如何從這個 11 到達 00 并且距離最短呢?根據(jù)上面的做法,我們可以從 11 開始,先在水平方向移動,直到與 00 在同一列,隨后再在豎直方向上移動,直到到達 00 的位置。這樣一來,從一個固定的 11 走到任意一個 00,在距離最短的前提下可能有四種方法:
只有 水平向左移動 和 豎直向上移動;
只有 水平向左移動 和 豎直向下移動;
只有 水平向右移動 和 豎直向上移動;
只有 水平向右移動 和 豎直向下移動。
動態(tài)規(guī)劃+深度遍歷
class Solution {
public int[][] updateMatrix(int[][] mat) {
int m=mat.length;
int n=mat[0].length;
int[][] dp=new int[m][n];
for(int i=0;i<m;i++){
Arrays.fill(dp[i],Integer.MAX_VALUE/2);
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(mat[i][j]==0){
dp[i][j]=0;
}
if(i+1<m){
dp[i+1][j]=Math.min(dp[i][j]+1,dp[i+1][j]);
}
if(j+1<n){
dp[i][j+1]=Math.min(dp[i][j]+1,dp[i][j+1]);
}
}
}
for(int i=m-1;i>=0;i--){
for(int j=n-1;j>=0;j--){
if(mat[i][j]==0){
dp[i][j]=0;
}
if(i-1>=0){
dp[i-1][j]=Math.min(dp[i][j]+1,dp[i-1][j]);
}
if(j-1>=0){
dp[i][j-1]=Math.min(dp[i][j]+1,dp[i][j-1]);
}
}
}
return dp;
}
}
劍指 Offer 60. n個骰子的點數(shù)
這個關鍵是確定前一次和后一次篩子的數(shù)組要配置好。
class Solution {
public double[] dicesProbability(int n) {
double[] dp=new double[6];
Arrays.fill(dp,1.0/6.0);
int left=n;
//
for(int i=2;i<=n;i++){
double[] tmp=new double[5*i+1];
for(int j=0;j<dp.length;j++){
for(int k=0;k<6;k++){
tmp[j+k]+=dp[j]/6;
}
}
dp=tmp;
}
return dp;
}
}