LeetCode股票问题大全解

本文详细探讨了LeetCode上的6道股票问题,包括不同限制条件下的最佳买卖时机。通过状态穷举方法,分析每天买入、卖出和无操作的选择,并考虑交易次数和持有状态的影响。介绍了针对这些问题的解决方案,涉及LeetCode121到123以及188、309、714题。
摘要由CSDN通过智能技术生成

LeetCode上有6道股票问题,他们其实就是数组中是否存在数的差值最大,加上各种限制

  • 数组中两个数的差值最大
  • 数组中找出2对数使得其对应的差值的和最大
  • 数组中找出k对数使得其对应的差值的和最大
  • 数组中找出不限制对数使其对应的差值的和最大
  • 数组中找出跳跃一个元素的对数使得差值的和最大
  • 数组中找出不限制对数使得其差值最大(有附加损失)

这里我们用动态规划,利用状态进行穷举,我们具体到每一天,看看总共有几种可能的状态,再找出每个状态对应的选择。我们要穷举所有的状态,穷举的目的是根据对应的选择更新状态。听起来很抽象,只要记住[状态]和选择两个词就行,

for 状态1 in 状态1的所有取值:
    for 状态2 in 状态2的所有取值:
        for ...
            dp[状态1][状态2][...] = 择优(选择1,选择2...)

比如说这个问题,每天都有三种「选择」:买入、卖出、无操作,我们用 buy, sell, rest 表示这三种选择。但问题是,并不是每天都可以任意选择这三种选择的,因为 sell 必须在 buy 之后,buy 必须在 sell 之后。那么 rest 操作还应该分两种状态,一种是 buy 之后的 rest(持有了股票),一种是 sell 之后的 rest(没有持有股票)。而且别忘了,我们还有交易次数 k 的限制,就是说你 buy 还只能在 k > 0 的前提下操作。

这个问题的状态有3个,第一个是天数,第二个是允许交易的最大次数,第三个是当钱的持有状态(寄之前说的reset的状态,我们不妨用1表示持有,0表示没有持有),然后我们用一个三维数组就可以装下这几种状态的全部组合

dp[i][k][0 or 1]
0 <= i <= n-1, 1 <= k <= K
n 为天数,大 K 为最多交易数
此问题共 n × K × 2 种状态,全部穷举就能搞定。

for 0 <= i < n:
    for 1 <= k <= K:
        for s in {
   0, 1}:
            dp[i][k][s] = max(buy, sell, rest)


在这里插入图片描述
状态转移方程:
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])

baseCase

dp[0][k][0]= 0
dp[0][k][1] =Integer.MinVale/2
dp[i][0][1] = Integer.MinvAL/2
dp[i][0][0]=0


LeetCode121 买股票的最佳时机

在这里插入图片描述


package com.zj.FDynamicProgramming.taolu;

/**
 * @Author Zhou Jian
 * @Date 2020/8/8
 */
public class Problem121 {
   


    /**
     * dp[i][k][0] 第i天允许操作k次不持有股票获利最大
     * dp[i][k][1] 第i天允许操作k次不持有股票获利最大
     *
     * dp[i][k][0] = max(dp[i-1][k][0],dp[i-1][k][1]+nums[i-1]
     * dp[i][k][1] = max(dp[i-1][k][1],dp[i-1][k-1][0]-nums[i-1])
     *
     * dp[0][k][0] = 0
     * dp[i][0][1] = 不可能
     *
     * @param prices
     * @return
     */
    public int maxProfit(int[] prices) {
   

        if(prices==null||prices.length==0) return 0;

        int[][] dp = new int[prices.length+1][2];

        dp[0][0] = 0;

        for(int i=0;i<prices.length+1;i++){
   
            if(i==0){
   
                dp[i][0] = 0;
                dp[i][1]=Integer.MIN_VALUE;
                continue;
            }
            dp[i][0] = Math.max(dp[i-1][0],dp[
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值