- 买卖股票的最佳时机 II
子问题
每天的股票是否买入
确定状态
cash 每天持有的现金 precash 昨天持有的现金
stock 每天持有的股票 prestock 昨天持有的股票
边界状态
第一天是否买入股票
否 cash=0;是 stock=-prices[i]
状态转移
cash=Math.max(precash,prestock+prices[i]);//继续不买,还是昨天买今天卖
stock=Math.max(prestock,precash-prices[i]);//继续持有,还是昨天不买今天买
class Solution {
public int maxProfit(int[] prices) {
if(prices.length<2){
return 0;
}
int cash=0;
int stock=-prices[0];
int precash;
int prestock;
for(int i=1;i<prices.length;i++){
precash=cash;
prestock=stock;
cash=Math.max(precash,prestock+prices[i]);
stock=Math.max(prestock,precash-prices[i]);
}
return cash;
}
}
- 最长回文子串
子问题
每个子串是否为回文,输出最长的一个
确定状态
dp[i][j]:i~j是否为回文
边界状态
dp[i][i],单独一个字符也是回文
状态转移
i~j若为回文,则头尾相同,且内部是回文
dp[i][j]= (i==j && dp[i+1][j-1])
有[i+1][j-1],就要考虑边界,显然,如果i+1~j-1不成区间,也就是内部是一个单字或者是空的情况下,只要头尾相等,他就是回文。
即 j-1-(i+1)+1<2 => j-i<3 时,直接判定是回文
class Solution {
public String longestPalindrome(String s) {
int len=s.length();
if(len<2){
return s;
}
boolean[][] dp=new boolean[len][len];
int maxlen=1;
int start=0;
for(int i=0;i<len;i++){
dp[i][i]=true;
}
for(int j=1;j<len;j++){
for(int i=0;i<j;i++){
if(s.charAt(i)==s.charAt(j)){
if(j-i<3){
dp[i][j]=true;
}else{
dp[i][j]=dp[i+1][j-1];
}
}else{
dp[i][j]=false;
}
if(dp[i][j]){
int xlen=j-i+1;
if(xlen>maxlen){
maxlen=xlen;
start=i;
}
}
}
}
return s.substring(start, start + maxlen);
}
}
- 三角形最小路径和
子问题
从底向上,每一层到达底层的最小路径和
确定状态
dp[i]:该层i位置到达底层的最短路径和
边界状态
处于底层
状态转移
每一层dp[i]+=下一层Math.min(dp[i],dp[i+1])
class Solution {
public int minimumTotal(List<List<Integer>> triangle) {
if (triangle == null || triangle.size() == 0){
return 0;
}
int[] dp = new int[triangle.size()+1];
for (int i = triangle.size() - 1; i >= 0; i--) {
List<Integer> curTr = triangle.get(i);
for (int j = 0; j < curTr.size(); j++) {
dp[j] = Math.min(dp[j],dp[j+1]) + curTr.get(j);
}
}
return dp[0];
}
}