【LeetCode】动态规划—714. 买卖股票的最佳时机含手续费(附完整Python/C++代码)

news2024/10/12 20:22:06

动态规划—714. 买卖股票的最佳时机含手续费

  • 题目描述
  • 前言
  • 基本思路
    • 1. 问题定义
    • 2. 理解问题和递推关系
      • 状态定义:
      • 状态转移公式:
      • 初始条件:
    • 3. 解决方法
      • 动态规划方法
      • 伪代码:
    • 4. 进一步优化
    • 5. 小总结
  • Python代码
      • Python代码解释总结:
  • C++代码
      • C++代码解释总结:
  • 总结

题目描述

在这里插入图片描述

前言

带手续费的买卖股票问题 是动态规划的经典问题之一。给定一个数组 prices 表示股票每天的价格,并且每次卖出股票时需要支付一定的手续费 fee,目标是通过在任意天买入或卖出股票,以最大化利润。该问题要求我们考虑每次交易时手续费的影响,并通过动态规划的方法来规划最优的买卖操作。


基本思路

1. 问题定义

给定一个数组 prices,其中 prices[i] 表示第 i 天的股票价格,同时给定一个整数 fee 代表交易时需要支付的手续费。目标是通过多次交易获得最大利润(可以多次买卖股票),但每次交易(买入和卖出)需要支付 fee

2. 理解问题和递推关系

为了帮助我们理解这个问题,我们可以定义两种状态来表示每一天的持有情况。

状态定义:

  1. 持有股票的状态(hold

    • hold[i] 表示在第 i 天结束时,我们持有股票时的最大收益。
    • 这个状态可以从两种情况转移而来:要么是之前已经持有并继续持有(hold[i-1]),要么是今天刚刚买入股票。
  2. 未持有股票的状态(sell

    • sell[i] 表示在第 i 天结束时,我们不持有股票时的最大收益。
    • 这个状态可以从两种情况转移而来:要么是之前已经不持有并继续不持有(sell[i-1]),要么是今天卖出了股票。

状态转移公式:

  1. 持有股票的状态转移:要么我们继续持有股票,要么今天刚刚买入股票:
    h o l d [ i ] = max ⁡ ( h o l d [ i − 1 ] , s e l l [ i − 1 ] − p r i c e s [ i ] ) hold[i] = \max(hold[i-1], sell[i-1] - prices[i]) hold[i]=max(hold[i1],sell[i1]prices[i])

    • hold[i-1] 表示我们在 i-1 天已经持有股票且继续持有;
    • sell[i-1] - prices[i] 表示今天买入股票的收益。
  2. 未持有股票的状态转移:要么我们继续不持有股票,要么今天卖出了股票并获得利润:
    s e l l [ i ] = max ⁡ ( s e l l [ i − 1 ] , h o l d [ i − 1 ] + p r i c e s [ i ] − f e e ) sell[i] = \max(sell[i-1], hold[i-1] + prices[i] - fee) sell[i]=max(sell[i1],hold[i1]+prices[i]fee)

    • sell[i-1] 表示我们在 i-1 天不持有股票且继续不持有;
    • hold[i-1] + prices[i] - fee 表示今天卖出股票的收益,需要减去交易手续费 fee

初始条件:

  • hold[0] = -prices[0]:表示在第 0 天买入股票后的收益(即负的股票价格)。
  • sell[0] = 0:在第 0 天不持有股票,收益为 0。

3. 解决方法

动态规划方法

  1. 初始化状态hold[0]sell[0] 表示初始的持有和不持有股票的状态。
  2. 状态转移:通过递推公式更新每一天的持有股票和不持有股票状态。
  3. 最终结果:在最后一天,最大收益必然是不持有股票时的收益,即 sell[n-1]

伪代码:

initialize hold[0] = -prices[0], sell[0] = 0
for each day i from 1 to n-1:
    hold[i] = max(hold[i-1], sell[i-1] - prices[i])
    sell[i] = max(sell[i-1], hold[i-1] + prices[i] - fee)
return sell[n-1]

4. 进一步优化

  • 空间优化:由于 dp[i] 只依赖于 dp[i-1],我们可以将 holdsell 的状态用常量来存储,优化空间复杂度为 O(1)

5. 小总结

  • 问题思路:通过将状态分为持有股票和不持有股票的两种情况,动态规划可以清晰描述每一天的操作。
  • 时间复杂度:该方法的时间复杂度为 O(n),空间复杂度可以优化为 O(1)

以上就是买卖股票的最佳时机含手续费问题的基本思路。


Python代码

class Solution:
    def maxProfit(self, prices: list[int], fee: int) -> int:
        if not prices:
            return 0

        # 初始化第0天的状态
        hold = -prices[0]
        sell = 0

        for i in range(1, len(prices)):
            # 更新状态
            new_hold = max(hold, sell - prices[i])
            new_sell = max(sell, hold + prices[i] - fee)

            # 更新持有和不持有股票的状态
            hold, sell = new_hold, new_sell

        # 返回不持有股票时的最大收益
        return sell

Python代码解释总结:

  1. 初始化:在第 0 天,如果持有股票,则收益为 -prices[0],否则为 0
  2. 状态转移:通过递推公式更新每一天的 holdsell 状态。
  3. 返回结果:最终返回不持有股票时的最大收益 sell

C++代码

#include <vector>
#include <algorithm>
using namespace std;

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        if (prices.empty()) return 0;

        int hold = -prices[0];  // 初始化第0天持有股票的状态
        int sell = 0;           // 初始化第0天不持有股票的状态

        for (int i = 1; i < prices.size(); ++i) {
            // 更新持有和不持有股票的状态
            int new_hold = max(hold, sell - prices[i]);
            int new_sell = max(sell, hold + prices[i] - fee);
            hold = new_hold;
            sell = new_sell;
        }

        // 返回不持有股票时的最大收益
        return sell;
    }
};

C++代码解释总结:

  1. 初始化:在第 0 天,如果持有股票,则收益为 -prices[0],否则为 0
  2. 状态转移:通过递推公式更新每一天的 holdsell 状态。
  3. 返回结果:在最后一天,返回不持有股票时的最大收益 sell

总结

  • 问题核心:带手续费的买卖股票问题通过将状态划分为持有股票和不持有股票两种情况,通过动态规划可以有效求解。
  • 时间复杂度:时间复杂度为 O(n),适合处理大规模输入。
  • 空间优化:由于每个状态只依赖前一天的状态,因此可以将空间复杂度优化为 O(1),这在处理大规模输入时是非常有效的。

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

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

相关文章

出海电商新怎样用海外云手机引流?

随着互联网行业的迅猛发展&#xff0c;出海电商、海外社交媒体营销以及游戏产业等领域对技术工具的需求不断增加。在这种趋势下&#xff0c;海外云手机作为一种新型解决方案&#xff0c;正在受到广泛关注。 特别是在出海电商中&#xff0c;平台如亚马逊、速卖通、eBay等通过结合…

Mysql(八) --- 视图

文章目录 前言1.什么是视图&#xff1f;2.创建视图3. 使用视图4. 修改数据4.1.注意事项 5. 删除视图6.视图的优点 前言 前面我们学习了索引&#xff0c;这次我们来学习视图 1.什么是视图&#xff1f; 视图是一个虚拟的表&#xff0c;它是基于一个或多个基本表或其他视图的查询…

8款宝藏手机app,适配安卓和苹果手机

好用的手机APP太多&#xff0c;差点挑花了眼&#xff01;今天来分享4款苹果手机和4款安卓手机上的宝藏软件&#xff0c;看看你喜欢哪一款~ IOS系统APP 1.搜图神器 一款拥有海量图片资源的图片搜索神器&#xff0c;它聚合海内外知名搜索引擎&#xff0c;想要图片直接搜索就行…

用java来编写web界面

一、ssm框架整体目录架构 二、编写后端代码 1、编写实体层代码 实体层代码就是你的对象 entity package com.cv.entity;public class Apple {private Integer id;private String name;private Integer quantity;private Integer price;private Integer categoryId;public…

【JavaScript】LeetCode:61-65

文章目录 61 课程表62 实现Trie&#xff08;前缀树&#xff09;63 全排列64 子集65 电话号码的字母组合 61 课程表 Map BFS拓扑排序&#xff1a;将有向无环图转为线性顺序。遍历prerequisites&#xff1a;1. 数组记录每个节点的入度&#xff0c;2. 哈希表记录依赖关系。n 6&a…

Vulnhub靶场案例渗透[7]- DC7

文章目录 1. 靶场搭建2. 信息收集2.1 确定靶机ip2.2 服务信息收集2.3 社工信息收集 3. 提权 1. 靶场搭建 靶场源地址 检验下载文件的检验码&#xff0c;对比没问题使用vmware打开 # windwos 命令 Get-FileHash <filePath> -Algorithm MD5 # linux md5sum filepath2. 信…

视频汇聚平台EasyCVR支持云端录像丨监控存储丨录像回看丨录像计划丨录像配置

EasyCVR视频汇聚融合平台&#xff0c;是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。平台以其强大的视频处理、汇聚与融合能力&#xff0c;在构建视频监控系统中展现出了独特的优势。 EasyCVR视频汇聚平台可接入传统监控行业中高清网络摄像机的RTSP…

提升实验室效率的秘籍

有组织、高效的实验室而言&#xff0c;业务“人、机、料、法、环、测”的多维度发展至关重要&#xff0c;为了提高实验室管理效率和质量&#xff0c;许多实验室开始采用LIMS&#xff08;实验室信息管理系统&#xff09;软件来辅助管理。LIMS软件能够帮助实验室实现信息化、自动…

leetcode 3217 从链表中移除在数组中的结点

1.题目要求: 给你一个整数数组 nums 和一个链表的头节点 head。从链表中移除所有存在于 nums 中的节点后&#xff0c;返回修改后的链表的头节点。 示例 1&#xff1a; 输入&#xff1a; nums [1,2,3], head [1,2,3,4,5] 输出&#xff1a; [4,5] 解释&#xff1a; 移除数值…

Java中的枚举

1.1 认识枚举 枚举是一种特殊的类&#xff0c;它的格式是&#xff1a; public enum 枚举类名{枚举项1,枚举项2,枚举项3; } 其实枚举项就表示枚举类的对象&#xff0c;只是这些对象在定义枚举类时就预先写好了&#xff0c;以后就只能用这几个固定的对象。 定义一个枚举类&am…

使用VS2015编写C语言程序

前面我们给出了一段完整的C语言代码&#xff0c;就是在显示器上输出“C语言中文网”&#xff0c;如下所示&#xff1a; #include <stdio.h>int main(){puts("C语言中文网");return 0;}本节我们就来看看如何通过 VS2015 来运行这段代码。 1) 创建项目&#xf…

QD1-P8 HTML 格式化标签(font、pre、b、strong、i、u、del、s、sub、sup)

本节学习&#xff1a;HTML 格式化标签。 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p8 ‍ 一、font 标签 用途&#xff1a;定义文本的字体大小、颜色和 face&#xff08;字体类型&#xff09;。 示例 <!DOCTYPE html> <html><head><meta cha…

Tkinter:为什么多个Frame相互覆盖?

在 Tkinter 中&#xff0c;Frame 是一个容器部件&#xff0c;用于组织和管理布局。如果多个 Frame 出现在同一个父容器中并且看起来相互覆盖&#xff0c;通常与布局管理器的使用方式或控件的创建顺序有关。 以下是几个常见的原因和解决方案&#xff0c;帮助你了解为什么多个 F…

生产报工信息化全流程大讲解

在企业的生产管理中&#xff0c;生产报工是一个关键环节&#xff0c;但传统的生产报工方式存在诸多痛点&#xff0c;制约了企业的发展。随着数字化技术的发展&#xff0c;多个平台为企业提供了有效的解决方案。基于生产报工信息化方案报告》白皮书&#xff0c;本文深入探讨生产…

三菱FX3U PLC绝对定位- DRVA指令

指令格式 相关软元件一览 功能和动作 这是采用绝对驱动的单速定位指令。采用从原点(0点)开始的距离指定方式&#xff0c; 也被称为绝对驱动方式。 1、在指令执行过程中&#xff0c;即使改变操作数的内容&#xff0c;也不反映到当前的运行中。 在下次的指令驱动时才有效…

客户服务的未来趋势:智能化与人性化的融合

在当今这个日新月异的数字时代&#xff0c;企业的竞争已不再局限于产品或服务的本身&#xff0c;而是延伸到了客户体验的每一个细微之处。数字化转型作为推动这一变革的重要力量&#xff0c;正深刻改变着客户服务的面貌&#xff0c;使之变得更加智能、便捷且充满人性化。随着人…

最长回文子串-双下标动态规划

题目来源&#xff1a;Leetcode 5.最长回文子串 DP定义&#xff1a; 容易想到&#xff0c;用一个二维数字dp[i][j]来表示s[i:j]是否是回文串&#xff0c;如s“daba”。dp[1][3]1表示"aba"为回文串&#xff1b; 递归条件 想要判断字符串"aba"是否为回文…

MySQL--事务(详解)

目录 一、前言二、本文章目标三、什么是事务&#xff1f;四、事务的ACID特性五、为什么要使用事务六、如何使用事务6.1 查看支持使用事务的引擎6.2语法6.3 开启⼀个事务&#xff0c;执行更新后回滚6.4 开启一个事务更新后提交6.5 保存点6.6 自动/手动提交事务 七、事务的隔离性…

X86、ARM架构镜像

1. 简介 ARM 镜像和 x86 镜像是为不同处理器架构设计的软件镜像。ARM&#xff08;Advanced RISC Machine&#xff09;架构和 x86 架构是两种主流的处理器指令集架构&#xff0c;它们在设计和性能特点上有所不同。以下是 ARM 镜像和 x86 镜像的一些主要区别&#xff1a; 处理器架…

LangGraph入门(一)为什么要用LangGraph

阅读langgraph文档后编写&#xff0c;原文链接 https://langchain-ai.github.io/langgraph/concepts/high_level/ agent介绍 大语音模型LLMs是非常强大的&#xff0c;特别是LLMs与外部API或者检索数据库结合时&#xff0c;将使得的大模型如虎添翼。所以&#xff0c;在调用LLM之…