​ 121. 买卖股票的最佳时机 ​

动态规划:买卖股票的最佳时机_最小值

思路

贪心

因为股票就买卖一次,那么贪心自然就是取最左最小值,取最右最大值,那么得到的差值就是最大利润。

动态规划

  1. 确定dp数组(dp table)以及下标的含义
    dp[i][0] 表示第i天持有股票所得现金(一开始现金是0,那么加入第i天买入股票现金就是 -prices[i], 这是一个负数)。
    dp[i][1] 表示第i天不持有股票所得现金
    注意这里说的是“持有”,“持有”不代表就是当天“买入”!也有可能是昨天就买入了,今天保持持有的状态
  2. 确定递推公式
    如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来:第i-1天就持有股票,那么就保持现状;第i天买入股票。那么dp[i][0]应该选所得现金最大的,所以dp[i][0] = max(dp[i - 1][0], -prices[i]);
    如果第i天不持有股票即dp[i][1], 也可以由两个状态推出来:第i-1天就不持有股票,那么就保持现状;第i天卖出股票。同样dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
  3. dp数组如何初始化
    dp[0][0]表示第0天持有股票,此时的持有股票就一定是买入股票了,所以dp[0][0] -= prices[0];
    dp[0][1]表示第0天不持有股票,不持有股票那么现金就是0,所以dp[0][1] = 0;
  4. 确定遍历顺序
    从递推公式可以看出dp[i]都是有dp[i - 1]推导出来的,那么一定是从前向后遍历。

代码

贪心:

class Solution {
public int maxProfit(int[] prices) {
int ans = 0;
int low = Integer.MAX_VALUE;
for(int i=0;i<prices.length;i++){
low = Math.min(low,prices[i]);
ans = Math.max(ans,prices[i]-low);
}
return ans;
}
}


动态规划:

class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][2];
//第0天持有股票
dp[0][0] = -prices[0];
//第0天不持有股票
dp[0][1] = 0;
for(int i=1;i<prices.length;i++){
dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],prices[i]+dp[i-1][0]);
}
return dp[prices.length-1][1];
}
}