【买卖股票系列问题 -- 动规 + 其他转换方法】

news2024/11/17 7:44:07

目录:

  • 前言
  • 买卖股票的最佳时机
      • 题解1:找出最值区间
      • 题解2:问题转化:最大子序和
      • 题解3:动态规划
  • 买卖股票的最佳时机 II
      • 题解1:动态规划
      • 题解2:贪心
  • 买卖股票的最佳时机含冷冻期
      • 动态规划
  • 买卖股票的最佳时机含手续费
      • 动态规划
  • 买卖股票的最佳时机 III
      • 动态规划
  • 买卖股票的最佳时机 IV
      • 动态规划
  • 总结

前言

打怪升级:第80天

买卖股票的最佳时机

买卖股票的最佳时机:简单
这里是引用

题解1:找出最值区间

class Solution {
public:
    int maxProfit(vector<int>& prices) {
		int n=prices.size();
    	int max=prices[0];
    	int min=prices[0];
    	int sum=0;
    	for(int i=1; i<n; ++i)
    	{
    		if(prices[i] < min)	 max=min=prices[i];// 最大值需要在最小值之后 
    		if(prices[i] > max)  max=prices[i]; 
            if(max-min>sum) sum=max-min;
		}
		
		return sum;
    }
};

这里是引用

题解2:问题转化:最大子序和

class Solution {
public:
    int maxProfit(vector<int>& prices) {
		int ret=0;
		int sum=0;
		
		for(int i=1; i<prices.size(); ++i) // 转换为求解最大子序和
		{
			int dev = prices[i] - prices[i-1];
			sum = max(dev, dev + sum);
			ret = max(ret, sum);
		}
		
		return ret; 
    }
};

这里是引用

题解3:动态规划

在这里插入图片描述

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
       vector<vector<int> >dp(n, vector<int>(2, 0));
       dp[0][0] = -prices[0];

       for(int i=1; i<n; ++i)
       {
           dp[i][0] = max(dp[i-1][0], -prices[i]);
           dp[i][1] = max(dp[i-1][1], prices[i] + dp[i-1][0]);
       }

       return dp[n-1][1];
    }
};

这里是引用


买卖股票的最佳时机 II

买卖股票的最佳时机 II

题解1:动态规划

这里是引用

这里是引用

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int  n = prices.size();
        vector<vector<int> >dp(n, vector<int>(2, 0));
        dp[0][0] = -prices[0];

        for(int i=1; i<n; ++i)
        {
            dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]);
            dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i]);
        }

        return dp[n-1][1];
    }
};

在这里插入图片描述

对比两道题的状态转移方程:
这里是引用

题解2:贪心

这道题允许我们多次买卖,只要有的赚就可以买,这里有很明显的贪心思想,下面我们画图理解:
在这里插入图片描述在这里插入图片描述

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int ret=0;
        for(int i=1; i<prices.size(); ++i)
         ret += max(0, prices[i] - prices[i-1]);  // 今天卖出前一天的股票,收益为正

         return ret;
    }
};

这里是引用
在很多情况下,贪心都是一种很便利快速的解决问题的方法,不过想要看出这道题是否可以使用贪心,这对于我们还是有很大挑战的。


买卖股票的最佳时机含冷冻期

买卖股票的最佳时机含冷冻期

动态规划

这里是引用

买入:今天手里有股票,可以是昨天的没有卖,也可以是今天新买的;
可交易:现在手中没有股票,可以是今天没有买,也可以是冷冻期刚刚结束;
冷冻期:说明今天卖出了股票,进入一天冷冻期;

状态很多的情况下,画出状态机进行分析:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        vector<vector<int> >dp(n, vector<int>(3, 0)); // 三种状态 -- 买入、可交易、冷冻期
        dp[0][0] = -prices[0];

        for(int i=1; i<n; ++i)
        {
            dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]); 
            dp[i][1] = max(dp[i-1][1], dp[i-1][2]);
            dp[i][2] = dp[i-1][0] + prices[i];
        }

        return max(dp[n-1][1], dp[n-1][2]);
    }
};

这里是引用


买卖股票的最佳时机含手续费

买卖股票的最佳时机含手续费

动态规划

这里是引用在这里插入图片描述

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        int n = prices.size();
        vector<vector<int> >dp(n, vector<int>(2, 0));
        dp[0][0] = -prices[0];
// 不要纠结于会出现一只股票卖出多次的情况,既会减去多次fee,因为这里只是赋值,实际的dp[i-1][0] 和 prices[i]都没有改变,因此再次售卖也只会减去一次fee
        for(int i=1; i<n; ++i)
        {
            dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]);
            dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i] - fee); // 卖出的时候付手续费 -- 也可以买入的时候付
        }

        return dp[n-1][1];
    }
};


这里是引用


买卖股票的最佳时机 III

买卖股票的最佳时机 III

在这里插入图片描述

动态规划

在这里插入图片描述

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        vector<vector<int>>f(n, vector<int>(3, -prices[0])); // 买入状态
        vector<vector<int>>g(n, vector<int>(3, 0));          // 卖出状态

        for(int i=1; i<n; ++i)
        {
            for(int j=0; j<3; ++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) // 判断j是否合理
                    g[i][j] = max(g[i-1][j], f[i-1][j-1] + prices[i]);
            }
        }

        return max(g[n-1][0], max(g[n-1][1], g[n-1][2]));
    }
};

这里是引用


买卖股票的最佳时机 IV

买卖股票的最佳时机 IV

这里是引用
本题与上一题的唯一区别是:上一题最多交易2次,本题最多交易k次,我们只需要将上一题中的 3 改为 k + 1即可。

动态规划

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        int n = prices.size();
        vector<vector<int> >f(n, vector<int>(k+1, -prices[0]));
        vector<vector<int> >g(n, vector<int>(k+1, 0));

        for(int i=1; i<n; ++i)
        {
            for(int j=0; j<k+1; ++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-1][j], f[i-1][j-1] + prices[i]);
            }
        }

        int ret = 0;
        for(auto e : g[n-1]) // 最后一行取最大值
        ret = max(ret, e);

        return ret;
    }
};

这里是引用


总结

  1. 买卖股票问题与打家劫舍类问题一样,都属于多状态dp问题,既在第 i 个位置时,会有多种状态需要分析,例如:
    买卖股票:第 i 天 可以选择 持有股票,也可以不持有股票,
    打家劫舍:第 i 家 可以选择 进行偷窃,也可以不进行偷窃。
    甚至类似上面的,在第 i 天 时 一共进行了 多少次交易,这就需要再增加更多的状态表示进行区分。

  2. 上方我们在进行转移方程推导时画了好多图,例如:
    在这里插入图片描述
    这个状态转移图我们称之为:状态机,用来更加清楚地描述各个状态之间相互转换的情况,我们在之后写动态规划类题目时大都可以画出状态机来理清关系。

  3. dp[i][0] 只是考虑会买入, dp[i][1]只是考虑会卖出,实际上是否卖出要选择最大值。



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

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

相关文章

Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制

文章目录 Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制1. 前言2. 项目环境搭建3. 项目路由机制3.1. 1&#xff09;先搜索pom.xml文件&#xff0c;看看使用了什么框架3.2. 2&#xff09;确定是否是spring的路由机制3.3. 3&#xff09;确定自写路由机制的…

双指针(7)_单调性_三数之和

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 双指针(7)_单调性_三数之和 收录于专栏【经典算法练习】 本专栏旨在分享学习C的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 题目…

【Redis】redis5种数据类型(string)

目录 redis5种数据类型和内部编码方式 redis单线程模型 string字符串类型相关命令 SET GET MSET MGET SETNX SETEX ​编辑PSETEX value值为整数&#xff0c;进行加减操作 INCR INCRBY DECR DECRBY INCRBYFLOAT APPEND GETRANGE SETRANGE STRLEN string的…

VMwareWorkstation安装UOS系统(1070版本)教程

UOS系统是一款国产信创操作系统。目前市面上主流的系统版本是1070&#xff0c;下面我们用虚拟机来安装一下这款系统。 创建虚拟机 首先&#xff0c;我们先打开VMwareWorkstation软件&#xff0c;新建虚拟机 选择自定义&#xff0c;点击下一步 点击下一步 选择稍后安装操作系统…

【通信管理之c++基础01】std::future

std::future https://en.cppreference.com/w/cpp/thread/future https://cplusplus.com/reference/future/future/ std::async #

实验一 局域网设计

一、实验目的 1.掌握网络工程中需求分析方法。 2.子网IP地址规划及子网间互相通信的方法。 3.掌握局域网的构建方法。 二、实验描述 某中学拟建设一个校园网&#xff0c;网络使用192.168.10.0/24这个地址段。计算机主要分布如下&#xff1a;两个学生机房各为10台&#xff…

数据库课程 CMU15-445 2023 Fall Project-0 项目记录

0. 实验结果 1. 环境配置 1.1 虚拟机Ubuntu 22.04.4 LTS 1.2 Vscode 插件安装clangd&#xff1a;代码补全 1.3 参考官方Project 0完成环境配置 1.4 获取到的代码&#xff0c;切换分支到2023 Fall git checkout fc57dab // 仓库中2023 Fall release版本的哈希值 git branch d…

WPF 保姆级教程怎么实现一个树形菜单

先看一下效果吧: 我们直接通过改造一下原版的TreeView来实现上面这个效果 我们先创建一个普通的TreeView 代码很简单: <TreeView><TreeViewItem Header"人事部"/><TreeViewItem Header"技术部"><TreeViewItem Header"技术部-1&q…

低代码平台:助力企业数字化转型的利器

正文&#xff1a; 在数字化时代的浪潮中&#xff0c;企业需要快速适应市场变化和技术进步。传统的软件开发方法往往由于开发周期长、成本高和对技术人员的依赖程度高&#xff0c;难以满足企业的快速响应需求。此时&#xff0c;低代码平台&#xff08;Low-Code Platform&#x…

干货分享|分享一款微软出品的工作效率神器 PowerToys

工具介绍&#xff1a;Microsoft PowerToys 是一组实用工具&#xff0c;可帮助高级用户调整和简化其 Windows 体验&#xff0c;从而提高工作效率。 安装步骤&#xff1a;直接打开微软商店安装即可&#xff0c;并且可以保证下载到最新版本。 功能介绍&#xff1a; 高级粘贴 高级…

js react 笔记 2

起因&#xff0c; 目的: 记录一些 js, react, css 1. 生成一个随机的 uuid // 需要先安装 crypto 模块 const { randomUUID } require(crypto);const uuid randomUUID(); console.log(uuid); // 输出类似 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d 2. 使用 props, 传递参数…

[uniapp/wx小程序] 关于cover-view滚动/点击穿透问题的解决方案/cover-view 的坑

情况&#xff1a;如果在原生组件上&#xff0c;搞了一些弹窗、覆盖层、操作栏等等的东西&#xff0c;有层级的情况&#xff0c;就会出现事件穿透的问题 问题&#xff1a;自然会想到官方给出的解决方案&#xff1a;使用cover-view。但有时穿透问题虽然解决了&#xff0c;但会出…

【NanoEdgeAIStudio】初次体验

本文前言 NanoEdge ai Studio是ST提供的免费软件&#xff0c;可以轻松地将ai添加到任何Arm Cortex-M MCU上运行的任何嵌入式项目中。官网首页&#xff1a;NanoEdge AI Studio&#xff0c;官方文档&#xff1a;AI:NanoEdge AI Studio。官方文档写的很详细&#xff0c;建议观看。…

Python 从入门到实战12(流程控制-跳出循环语句)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们通过举例学习了流程控制语句中的循环语句。今天继续讨…

【数据结构】顺序表和链表——链表(包含大量经典链表算法题)

文章目录 1. 单链表1.1 概念与结构1.1.1 结点1.1.2 链表的性质1.1.3 链表的打印 1.2 实现单链表1.3 链表的分类1.4 单链表算法题1.4.1 移除链表元素1.4.2 反转链表1.4.3 链表的中间结点1.4.4 合并两个有序链表1.4.5 链表分割1.4.6 链表的回文结构1.4.7 相交链表1.4.8 环形链表1…

【运维监控】influxdb 2.0+grafana 监控java 虚拟机以及方法耗时情况(完整版)

关于java应用的监控本系列有文章如下&#xff1a; 【运维监控】influxdb 2.0telegraf 监控tomcat 8.5运行情况 【运维监控】influxdb 2.0grafana 监控java 虚拟机以及方法耗时情况 【运维监控】Prometheusgrafana监控tomcat运行情况 【运维监控】Prometheusgrafana监控spring b…

软考科目傻傻分不清?一次搞懂各科目考核内容!小白不再纠结!

2024年下半年软考报名已经逐步进入尾声了&#xff0c;大部分考生都已完成报名&#xff0c;但有不少小白因为是第一次报考&#xff0c;对各科目傻傻分不清&#xff0c;导致报错了科目…… 这种情况很可能会影响考试&#xff0c;浪费了一次报考机会。而为了尽量避免这一情况再发生…

个人简历 (自己设计的)

欢迎大家来观看。 代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" co…

国产“小钢炮”MiniCPM3-4B:小参数,大能量!

前沿科技速递&#x1f680; 在 AI 大模型浪潮中&#xff0c;国内厂商面壁智能再次突破&#xff0c;推出了其最新的“小钢炮”系列——MiniCPM 3.0。这款全新模型不仅实现了在移动设备上运行 GPT-3.5 级别的能力&#xff0c;而且具备超强的推理、检索与代码解释功能。MiniCPM 3.…

Python必知必会:程序员必须知道的22个Python单行代码!

今天给大家分享24个每个Python程序员都必须知道的单行代码&#xff0c;帮你写出更简洁、更优雅、更高效的代码。 1. 列表推导式 列表推导式&#xff08;List Comprehensions&#xff09;可以提供一种简洁的方式创建列表。相较于传统的循环&#xff0c;列表推导式更高效、可读…