目录
⌛序列型动态规划
👇Example 1(房屋染色)
public class Solution {
public int minCost(int[][] costs) {
int n = costs.length;
int[][] dp = new int[n+1][3];
dp[0][0]=0;
dp[0][1]=0;
dp[0][2]=0;
for(int i=1; i<=n; i++){
for(int j=0;j<3; j++){
dp[i][j] = Integer.MAX_VALUE;
for(int k=0;k<3;k++){
//相邻不能撞色
if(j==k){
continue;
}
//选择染色的最小花费
dp[i][j]=Math.min(dp[i][j],dp[i-1][k]+costs[i-1][j]);
}
}
}
//选出最小值
int ret = dp[n][0];
if(ret>dp[n][1]){
ret = dp[n][1];
}
if(ret >dp[n][2]){
ret = dp[n][2];
}
return ret;
}
}
👇Example 2(最少费用的爬台阶方法)
public class Solution {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
if(n == 0 || cost == null){
return 0;
}
int[] dp = new int[n+1];
//初始化
dp[0] = 0;
dp[1] = 0;
for(int i=2; i<=n;i++){
dp[i] = Math.min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]);
}
return dp[n];
}
}
👇Example 3(俄罗斯套娃信封)
public class Solution {
public int maxEnvelopes(int[][] envelopes) {
int n = envelopes.length;
if(n == 0 || envelopes == null){
return 0;
}
//排序
Arrays.sort(envelopes,new Comparator<int[]>(){
public int compare(int[] a, int[] b){
if(a[0] == b[0]){
return a[1]-b[1];
}else{
return a[0]-b[0];
}
}
});
int[] dp =new int[n+1];
dp[0] =0;
int ret = 0;//记录能装最大的信封数
for(int i=1; i<=n; i++){
dp[i] = 1;
for(int j=1;j<i; j++){
if(envelopes[i-1][0]>envelopes[j-1][0]
&& envelopes[i-1][1]>envelopes[j-1][1]){
dp[i] = Math.max(dp[j]+1,dp[i]);
}
}
ret = Math.max(dp[i], ret);
}
return ret;
}
}
👇Example 4(完美平方)
public class Solution {
public int numSquares(int n) {
int x = (int)Math.sqrt(n);
if(x*x == n){
return 1;
}
int[] dp = new int[n+1];
dp[0] = 0;
for(int i=1; i<=n; i++){
dp[i] = dp[i-1]+1;//最差的情况在上一次情况下+1
for(int j=1; j*j<=i; j++){
dp[i] =Math.min(dp[i-j*j]+1,dp[i]);
}
}
return dp[n];
}
}
👇Example 5(买卖股票的最佳时机)
public class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
int[][] dp = new int[n+1][5+1];
//初始化
dp[0][1] = 0;
for(int i=2; i<6; i++){
dp[0][i] =Integer.MIN_VALUE;
}
for(int i=1; i<=n; i++){
//处于1,3,5阶段
for(int j=1; j<=5; j+=2){
dp[i][j] = dp[i-1][j];
if(i>1 && j>1 && dp[i-1][j-1] != Integer.MIN_VALUE)
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-1]+prices[i-1]-prices[i-2]);
}
//处于1,4阶段
for(int j=2; j<5; j+=2){
dp[i][j] = dp[i-1][j-1];
if( i>1 &&dp[i-1][j] != Integer.MIN_VALUE){
dp[i][j] = Math.max(dp[i][j], dp[i-1][j]+prices[i-1]-prices[i-2]);
}
if(j>1 && i>1 && dp[i-1][j-2] != Integer.MIN_VALUE){
dp[i][j] = Math.max(dp[i-1][j-2]+prices[i-1]-prices[i-2],dp[i][j]);
}
}
}
int ret = Math.max(Math.max(dp[n][1], dp[n][3]), dp[n][5]);
return ret;
}
}
🎈博弈型动态规划
👇Example 6 (硬币排成线)
public class Solution {
/**
* @param n: An integer
* @return: A boolean which equals to true if the first player will win
*/
public boolean firstWillWin(int n) {
if(n == 0){
return false;
}
if(n<=2){
return true;
}
boolean[] dp = new boolean[n+1];
//初始化
dp[0] = false;
dp[1] = true;
dp[2] = true;
for(int i=3; i<=n; i++){
dp[i] = dp[i-1] == false || dp[i-2] == false;
}
return dp[n];
}
}