【错题集-编程题】买卖股票的最好时机(四)(动态规划)

news2024/9/27 12:14:02

力扣对应题目链接:188. 买卖股票的最佳时机 IV - 力扣(LeetCode)

牛客对应题目链接:买卖股票的最好时机(四)_牛客题霸_牛客网 (nowcoder.com)


一、分析题目

1、状态表示

为了更加清晰的区分买入卖出,我们换成有股票无股票两个状态。

  • f[i][j] 表示:第 i 天结束后,完成了 j 笔交易,此时处于有股票状态的最大收益。
  • g[i][j] 表示:第 i 天结束后,完成了 j 笔交易,此时处于无股票状态的最大收益。

2、状态转移方程

对于 f[i][j],也有两种情况能在第 i 天结束之后,完成 j 笔交易,此时手里有股票的状态:

  • i-1 天的时候,手里有股票,并且交易了 j 次。在第 i 天的时候,啥也不干。此时的收益为 f[i - 1][j]
  • i-1 天的时候,手里没有股票,并且交易了 j 次。在第 i 天的时候,买了股票。那么 i 天结束之后,就有股票了。此时的收益为 g[i - 1][j] - prices[i]

上述两种情况,我们需要的是最大值,因此 f 的状态转移方程为:

f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]

对于 g[i][j],我们有下⾯两种情况能在第 i 天结束之后,完成 j 笔交易,此时手里没有股票的状态:

  • i-1 天的时候,手里没有股票,并且交易了 j 次。在第 i 天的时候,啥也不干。此时的收益为 g[i - 1][j]
  • i-1 天的时候,手里有股票,并且交易了 j - 1 次。在第 i 天的时候,把股票卖了。那么 i 天结束之后,我们就交易了 j 次。此时的收益为 f[i - 1][j - 1] + prices[i]

上述两种情况,我们需要的是最大值,因此 g 的状态转移方程为:

g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + prices[i])

它们之间交易关系如下:


3、初始化

由于需要用到 i=0 时的状态,因此我们初始化第一行即可。
  • 当处于第 0 天的时候,只能处于买入过⼀次的状态,此时的收益为 -prices[0] ,因f[0][0] = - prices[0]
  • 为了取 max 的时候,⼀些不存在的状态起不到干扰的作⽤,我们统统将它们初始化为 -INF(用 INT_MIN 在计算过程中会有溢出的风险,这⾥ INF 折半取 0x3f3f3f3f ,足够小即可)。

4、填表顺序

从上往下填每一行,每一行从左往右,两个表⼀起填。

5、返回值

返回处于卖出状态的最大值,但是我们也不知道是交易了几次,因此返回 g 表最后一行的最大值。


6、优化

我们的交易次数是不会超过整个天数的一半的,因此我们可以先把 k 处理一下,优化一下问题的规模:k = min(k, n / 2)


二、代码

//力扣
//【动态规划-二维dp-2个状态】
class Solution {
    //f[i][j]:第i天结束后,完成了j次交易,此时处于“买入”状态下的最大利润
    //g[i][j]:第i天结束后,完成了j次交易,此时处于“卖出”状态下的最大利润
private:
    const int INF=0x3f3f3f3f;
public:
    int maxProfit(int k, vector<int>& prices) {
        int n=prices.size();
        k=min(k, n/2); //优化:处理最多交易次数
        vector<vector<int>> f(n, vector<int>(k+1, -INF));
        vector<vector<int>> g(n, vector<int>(k+1, -INF));
        f[0][0]=-prices[0], g[0][0]=0;
        for(int i=1; i<n; i++)
        {
            for(int j=0; j<=k; j++)
            {
                f[i][j]=max(f[i-1][j], g[i-1][j]-prices[i]);
                g[i][j]=g[i-1][j];
                if(j>=1) g[i][j]=max(g[i][j], f[i-1][j-1]+prices[i]);
            }
        }
        int res=0;
        for(int j=0; j<=k; j++)
            res=max(res, g[n-1][j]);
        return res;
    }
};

//【动态规划-二维dp-2k+1个状态】
class Solution {
    //dp[i][0] -- 没有操作
    //下面j为奇数:买入;j为偶数:卖出 (j的范围:1~2k-1)
    //dp[i][j] -- 第1~k次买入
    //dp[i][j+1] -- 第1~k次卖出
public:
    int maxProfit(int k, vector<int>& prices) {
        int n=prices.size();
        vector<vector<int>> dp(n, vector<int>(2*k+1));
        for(int j=1; j<2*k; j+=2)
            dp[0][j]=-prices[0];
        for(int i=1; i<n; i++)
        {
            for(int j=0; j<2*k; j+=2)
            {
                dp[i][j+1]=max(dp[i-1][j+1], dp[i-1][j]-prices[i]);
                dp[i][j+2]=max(dp[i-1][j+2], dp[i-1][j+1]+prices[i]);
            }
        }
        return dp[n-1][2*k];
    }
};
//牛客
#include <iostream>
#include <cstring>
using namespace std;

const int INF=0x3f3f3f3f;
const int N=1010, M=110;
int prices[N];
int f[N][M], g[N][M];
//f[i][j]:第i天结束后,完成了j次交易,此时处于“买入”状态下的最大利润
//g[i][j]:第i天结束后,完成了j次交易,此时处于“卖出”状态下的最大利润

int main()
{
    int n, k;
    cin >> n >> k;
    for(int i=0; i<n; i++)
        cin >> prices[i];
    memset(f, -INF, sizeof(f));
    memset(g, -INF, sizeof(g));
    int res=0;
    f[0][0]=-prices[0], g[0][0]=0;
    for(int i=1; i<n; i++)
    {
        for(int j=0; j<=k; j++)
        {
            f[i][j]=max(f[i-1][j], g[i-1][j]-prices[i]);
            g[i][j]=g[i-1][j];
            if(j>0) g[i][j]=max(g[i][j], f[i-1][j-1]+prices[i]);
            res=max(res, g[i][j]);
        }
    }
    cout << res << endl;
    return 0;
}

//值得学习的代码
#include <iostream>
using namespace std;

const int N = 1010, M = 110;

int n, k, p[N];
int f[N][M], g[N][M];

int main()
{
    cin >> n >> k;
    for(int i = 0; i < n; i++) cin >> p[i];

    k = min(k, n / 2);
    for(int j = 0; j <= k; j++) f[0][j] = g[0][j] = -0x3f3f3f3f;
    f[0][0] = -p[0], g[0][0] = 0;

    for(int i = 1; i < n; i++)
    {
        for(int j = 0; j <= k; j++)
        {
            f[i][j] = max(f[i - 1][j], g[i - 1][j] - p[i]);
            g[i][j] = g[i - 1][j];
            if(j >= 1) g[i][j] = max(g[i][j], f[i - 1][j - 1] + p[i]);
        }
    }

    int ret = 0;
    for(int j = 0; j <= k; j++) ret = max(ret, g[n - 1][j]);

    cout << ret << endl;

    return 0;
}

三、反思与改进

买卖股票这种类似有系列的题目,需要把核心知识点彻底弄熟。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1920087.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【从零开始实现stm32无刷电机FOC】【实践】【4/6 stm32高级定时器】

点击查看本文开源的完整FOC工程 在完成理论方面的准备后&#xff0c;是可以进行写代码实现了&#xff0c;但是stm32单片机提供了不少可以用于电机控制的硬件外设&#xff0c;充分利用这些硬件资源&#xff0c;可以减少代码量以及提高运行性能。 本文使用的stm32型号为喜闻乐见的…

天环公益首发原创开发进度网站 带后台

天环公益计划首发原创开发进度网站 带后台 后台地址是&#xff1a;admin.php 后台没有账号密码 这个没有数据库 有能力的可以自己改 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/89520358 更多资源下载&#xff1a;关注我。

位图 、Max Sum、滑动窗口

这篇博客主要总结一下&#xff0c;这两天刷的算法题&#xff1a; 判断字符是否唯一 题目意思很简单不再解读&#xff0c;拿到这道题&#xff0c;其实不难看出哈希表可以直接秒了&#xff0c;注意这是一道面试题&#xff0c;在oj上可以哈希表秒了&#xff0c;如果面试官要求不使…

如何连接到公司的服务器?

1.下载FileZilla FileZilla的下载与安装以及简单使用&#xff08;有图解超简单&#xff09;-CSDN博客 2.打开 3.输入主机 用户名 密码 端口 注&#xff1a;主机支持的协议类型&#xff1a; 4.连接成功 其他方式也有很多&#xff0c;比如通过cmd&#xff0c;html网页等等 3个…

Apache Doris + Apache Hudi 快速搭建指南|Lakehouse 使用手册(一)

作者&#xff1a;SelectDB 技术团队 导读&#xff1a;湖仓一体&#xff08;Data Lakehouse&#xff09;融合了数据仓库的高性能、实时性以及数据湖的低成本、灵活性等优势&#xff0c;帮助用户更加便捷地满足各种数据处理分析的需求。在过去多个版本中&#xff0c;Apache Doris…

下载动画人物

1、网址&#xff1a;动画 2、点击Characters 3、搜索人物 4、点击弹出的人物&#xff0c;弹出对话框选择USE THIS CHARACTER 5、下载 6、点击Animations&#xff0c;搜索walk 7、点击UPLOAD CHARACTER&#xff0c;看到男孩步行&#xff0c;选择In Place&#xff0c;点击下载&…

浅谈后置处理器组件提取器相关的Apply to

浅谈后置处理器组件提取器相关的Apply to 在Apache JMeter中&#xff0c;“提取器”&#xff08;通常指的是正则表达式提取器、JSON路径提取器或CSS/JQuery提取器等&#xff09;是用来从服务器响应中提取信息的重要组件。这些信息可以是cookies、session IDs、特定的文本或者任…

作业一:ER图 作业:二QQ项目思路 作业三:实现QQ的登录与注册界面

一、ER图 二、QQ项目思路&#xff1a;客户端功能&#xff0c;服务器端功能的实现 1.登录注册&#xff1a; 将基本信息如手机号码&#xff0c;验证码&#xff0c;还有已有的账号及账号相关信息等存入数据库中&#xff0c;登录方式为账号密码登录&#xff0c;还有忘记密码用邮箱…

023-GeoGebra中级篇-几何对象之圆锥曲线

圆锥曲线是解析几何中的重要部分&#xff0c;它们包括椭圆、双曲线、抛物线和圆。通过使用预先定义的变量&#xff08;如数值、点和向量&#xff09;&#xff0c;我们可以动态地构建这些曲线的方程&#xff0c;并观察它们如何随变量的变化而变化。本文将介绍如何通过定义变量来…

TikTok 入局小游戏,小游戏出海赛道大热,开发者如何抢滩海外市场?

国内小游戏市场的竞争日益激烈&#xff0c;开发成本上涨、买量的投入成本飙升&#xff0c;对小团队和个人开发者的资金要求量高。除此以外&#xff0c;单款游戏从软著、备案、到认证所需要的时间和费用都大幅提升&#xff0c;也对小游戏市场造成重大影响。重压之下&#xff0c;…

旅游景区度假村展示型网站如何建设渠道品牌

景区、度假村、境外旅游几乎每天的人流量都非常高&#xff0c;还包括本地附近游等&#xff0c;对景区及度假村等固定高流量场所&#xff0c;品牌和客户赋能都是需要完善的&#xff0c;尤其是信息展示方面&#xff0c;旅游客户了解前往及查看信息等。 通过雨科平台建设景区度假…

[图解]分析模式-01-概述1

1 00:00:01,380 --> 00:00:01,770 好 2 00:00:02,340 --> 00:00:06,440 非常感谢大家能够来上我们 3 00:00:06,450 --> 00:00:07,960 分析模式高阶的课程 4 00:00:09,310 --> 00:00:13,440 这个内容之前在分析设计高阶 5 00:00:13,450 --> 00:00:17,840 也就…

客户反馈的智能分析:Kompas.ai如何转化用户声音为行动

客户反馈是企业改进产品和服务、提升客户满意度的重要资源。在数字化时代&#xff0c;如何有效收集和分析客户反馈&#xff0c;将其转化为实际行动&#xff0c;成为企业面临的挑战。Kompas.ai&#xff0c;一款智能客户反馈分析工具&#xff0c;正帮助品牌实现这一目标。 客户反…

nginx 正常访问,刷新404

问题描述&#xff1a; 部署完成前端服务&#xff0c;浏览器正常访问没有问题&#xff0c;但是F5刷新的时候&#xff0c;会提示404&#xff0c;丢失了资源。 解决办法&#xff1a; 在nginx配置中增加如下代码&#xff1a; try_files $uri $uri/ /index.html;

【Linux】进程间通信——命名管道和共享内存

目录 命名管道&#xff08;named pipe&#xff09; 命令行中使用 代码中使用 共享内存&#xff08;shared memory&#xff09; shmget ipcs命令 shmctl shmat/shmdt 简单通信 命名管道&#xff08;named pipe&#xff09; 之前我们说了匿名管道&#xff0c;但是匿名管道…

9717 取数对弈

首先&#xff0c;我们需要初始化两个数组&#xff0c;一个用于存储输入的数列a[]&#xff0c;另一个用于动态规划过程中存储中间结果的二维数组dp[][]。dp[i][j]表示从数列的第i个数到第j个数时&#xff0c;当前玩家&#xff08;甲方先手&#xff09;能够获得的最大得分。 接下…

2023 N1CTF-n1canary

文章目录 参考n1canary模板类和模板函数make_unique和unique_ptrstd::unique_ptr示例&#xff1a; std::make_unique示例&#xff1a; 结合使用示例 operator->getrandom逆向源码思路exp 参考 https://nese.team/posts/n1ctf2023/ n1canary 模板类和模板函数 template &…

从汇编层看64位程序运行——栈帧(Stack Frame)入门

在《从汇编层看64位程序运行——程序中的栈(Stack)结构及其产生的历史原因》一文中&#xff0c;我们讲解了X86体系架构下&#xff0c;程序的栈结构的特点。本文将介绍另外一个非常重要的结构——栈帧。 A stack frame, often just called a ‘frame,’ is a section of the sta…

大众汽车入职SHL在线测评、英语口语、招聘笔试如何通过、考点分析|备考建议

大众汽车入职在线测验真题考点分析&#xff0c;通过技巧&#xff1f; 大众汽车集团&#xff08;中国&#xff09;在招聘过程中&#xff0c;认知能力测试是评估候选人是否适合某个职位的重要环节。候选人会收到带有线上测评链接的邮件&#xff0c;测评包括胜任力潜力测试(Compe…

MySQL数字相关数据处理函数

目录 1. 随机数生成 rand ( ) 2. 四舍五入 round&#xff08;&#xff09; 3. 舍去 truncate ( ) 4. 向上/下取整 5. 空处理 ifnull&#xff08; x , y &#xff09; 1. 随机数生成 rand ( ) rand ( ) 生成 0 到 1 的随机数&#xff1b; rand ( x ) 生成 0 到 1 的随机数…