【代码训练营】day48 | 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II
创始人
2024-05-28 14:21:02
0

所用代码 java

买股票的最佳时机 LeetCode 121

题目链接:买股票的最佳时机 LeetCode 121 - 简单

思路

  • dp[i] [0] 、dp[i] [1] :在第i天持有股票所获得的最大利润为dp[i] [0] ;第 i天不持有股票dp[i] [1] 。所以我们在第i天的时候有持有和不持有股票这两种状态,且持有和不持有并不代表着这一天买或者卖,也可能是前面以及买入或者卖出的情况。

  • 递推公式:

    • dp[i] [0] = max(dp[i-1] [0], -prices[i])

      • dp[i-1] [0]:前一天持有股票的最大利润
      • -prices[i] :前一天买入股票,只买一次
    • dp[i-1] [1] = max(dp[i-1] [1], dp[i-1] [0] + prices[i])

      • dp[i-1] [1]:前一天不持有股票的最大利润
      • dp[i-1] [0] + prices[i]:第i天把股票给卖了,所以今日就要赚prices[i],且前一天买入时可能是赊账买入的,所以得加上前一天持有股票的状态
  • 初始化:

    • dp[0] [0]:- prices[0] 买入相当于是钱少了,所以是负数
    • dp[0] [1]:0 不买就是0元
  • 遍历顺序:1<=i

  • 打印dp数组

返回结果:

持有股票的最大利润或不持有股票的最大利润:max(dp[i] [0] , dp[i] [1])

其实不持有股票的最大利润肯定是比持有股票的利润大,可直接输出dp[i] [1]

class Solution {public int maxProfit(int[] prices) {int[][] dp = new int[prices.length][2];// 初始化、持有股票和不持有股票两种状态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], dp[i-1][0] + prices[i]);}// 最后一天不持有股票肯定比持有股票利润多return dp[prices.length-1][1];}
}

打印结果:

Your input:[7,1,5,3,6,4]
Output:5
Expected:5
stdout:dp[i][0] = -1   dp[i][1] = 0dp[i][0] = -1   dp[i][1] = 4dp[i][0] = -1   dp[i][1] = 4dp[i][0] = -1   dp[i][1] = 5dp[i][0] = -1   dp[i][1] = 5

总结

本题是股票买卖动态规划的基础,需好好理解持有股票与不持有股票,当天的利润应是如何获得的。

另外本题的dp数组可以压缩成一维的数组:

  • dp数组:

    • dp[0]:持有股票的最大利润
    • dp[1]:不持有股票的最大利润
  • 递推公式:

    • dp[0]:max(dp[0], -prices[i]) 前一天持有或前一天买入
    • dp[1]:max(dp[1], dp[0] + prices[i])前一天不持有或前一天卖出(前一天卖出=前一天持有+利润)
  • 初始化:

    • dp[0] = -prices[0] 第一天持有(相当于赊账买入)
    • dp[1] = 0 第一天不持有
class Solution {public int maxProfit(int[] prices) {int[] dp = new int[2];dp[0] = -prices[0]; // 持有股票dp[1] = 0; // 不持有股票for (int i = 1; i < prices.length; i++) {dp[0] = Math.max(dp[0], -prices[i]);dp[1] = Math.max(dp[1], dp[0] + prices[i]);
//            System.out.println("dp[0] =  "+dp[0] + "\tdp[1] = " +dp[1]);}return dp[1];}
}

打印结果:

Your input:[7,1,5,3,6,4]
Output:5
Expected:5
stdout:dp[0] =  -1 dp[1] = 0dp[0] =  -1 dp[1] = 4dp[0] =  -1 dp[1] = 4dp[0] =  -1 dp[1] = 5dp[0] =  -1 dp[1] = 5

贪心: 另外本题还可以直接使用贪心,只需要找到左边最小的数,最右的最大值,即可求得最大利润

class Solution {public int maxProfit(int[] prices) {int min = Integer.MAX_VALUE;int result = 0;for (int i = 0; i < prices.length; i++) {// 从左到右找到最小值min = Math.min(min, prices[i]);// 每次直接比较最大利润区间result = Math.max(result, prices[i] - min);}return result;}
}

买卖股票的最佳时机II LeetCode 122

题目链接:买卖股票的最佳时机II LeetCode 122 - 中等

思路

贪心的思路前面就做过了,这里主要考虑使用dp的方法。

和1不一样的地方:可以多次买入和卖出!

  • 不持有股票:前一天不持有,或者前一天刚好卖出
  • 卖出股票:卖股票可以卖多次,所以除了第一次赊账,后面都可以用前一天赚的钱来买股票,也就是前一天不持有股票的状态。
class Solution {public int maxProfit(int[] prices) {int[][] dp = new int[prices.length][2];// 初始化、持有股票和不持有股票两种状态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], dp[i-1][1]-prices[i]);// 不持有股票 => 前一天不持有股票或者今天刚好卖出(前一天持有的利润+卖出的利润)dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] + prices[i]);// System.out.println("dp[i][0] = " + dp[i][0] + "\tdp[i][1] = " + dp[i][1]);}// 最后一天不持有股票肯定比持有股票利润多return dp[prices.length-1][1];}
}

总结

同样,本题也可以写成一维数组的形式:

class Solution {public int maxProfit(int[] prices) {int[] dp = new int[2];dp[0] = -prices[0]; // 持有买票,买入(赊账)dp[1] = 0; // 不持有股票for (int i = 1; i < prices.length; i++) {// 持有 昨天持有或今日卖出(后面有钱了就不用赊账)dp[0] = Math.max(dp[0], dp[1]-prices[i]);// 不持有股票 昨天不持有或今日卖出(今日卖出昨日肯定就持有)dp[1] = Math.max(dp[1], dp[0]+prices[i]);}return dp[1];}
}

买卖股票重点:

  1. 今日持有股票的状态:

    1. 昨日不持有,今日才买入 => 就看前面是否赚钱

      • 一次买卖:-prices[i],相当于赊账去买
      • 多次买卖:dp[1]-prices[i],第一次赊账买,后面用前面持有是赚的钱去买
    2. 昨日持有 => dp[0]

  2. 今天不持有股票状态:

    1. 昨日持有,今日卖出 => 都是用昨日持有股票的状态(可能赊账买入),再加上今日卖这张股票赚的钱

      • 一次买卖:dp[0]+prices[i]
      • 多次买卖:dp[0]+prices[i]
    2. 不持有 => dp[1]

相关内容

热门资讯

原创 中... 最近,巴拿马阿赖汉市政府做出了一个引人注目的决定:在未提前通知的情况下,夜间悄然拆除了中巴公园及其标...
(粤港澳大湾区)大湾区仲裁员及... 中新社香港12月30日电 记者30日从香港特区政府律政司获悉,粤港澳三地法律部门当日正式发布《粤港澳...
中央商场控股子公司被泗阳规划局... 观点网讯:12月30日,南京中央商场(集团)股份有限公司发布公告,披露其控股子公司泗阳雨润中央购物广...
涉嫌内幕交易!千亿锂矿巨头被移... 锂矿龙头之一的赣锋锂业突发公告。 12月29日晚间,江西赣锋锂业集团股份有限公司(以下简称“赣锋锂业...
中央商场控股子公司泗阳雨润被江... 观点网讯:12月30日,南京中央商场(集团)股份有限公司发布公告,披露其控股子公司泗阳雨润中央购物广...
法治阳光照高墙:湖南芙蓉律所律... 为提升服刑人员的法治观念和回归社会的适应能力,帮助刑满释放人员顺利融入社会,近日,湖南芙蓉(常德)律...
强化执业纪律意识,筑牢合规执业... 为进一步强化律师执业纪律意识,持续提升律所规范化、专业化管理水平,2025年12月29日下午,湖南芙...
海口美兰区海府街道多部门联合化... “没想到这么快就能解决问题,现在上下楼方便多了,感谢你们为老百姓办实事!”12月29日,邮政西院小区...
重磅!国补最新政策落地 国家发展改革委 财政部关于2026年实施大规模设备更新和消费品以旧换新政策的通知 各省、自治区、直...
扫描“主播”|真人互动擦边影游... 视频编辑:张兆亿(01:24) “这能看?”“这种游戏是能播的吗?”“这几个女生衣服不能好好穿吗?...