【算法与数据结构】121、122、123、188、309、714、LeetCode买卖股票的最佳时机I II III IV+含冷冻期+含手续费

news2024/12/24 2:21:56

文章目录

  • 一、121、LeetCode买卖股票的最佳时机
    • 1.1 动态规划
    • 1.2 动态规划-滚动数组
  • 二、122、买卖股票的最佳时机 II
  • 三、123、买卖股票的最佳时机 III
  • 七、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、121、LeetCode买卖股票的最佳时机

在这里插入图片描述

1.1 动态规划

  思路分析

  • 第一步,动态数组的含义。本题股票买卖只能进行一次,需要考虑再第 i i i天的时候要不要持有股票(注意持有股票未必是买入第 i i i天的股票,也有可能购买前面天数的股票。它是一种状态,不是一种动作),由此产生了持有和不持有的两种状态。因此我们根据天数和是否持有股票这两个维度创建二维动态数组 d p [ i ] [ j ] dp[i][j] dp[i][j] d p [ i ] [ j ] dp[i][j] dp[i][j]一共两列: d p [ i ] [ 0 ] dp[i][0] dp[i][0]代表持有股票所得最多现金, d p [ i ] [ 1 ] dp[i][1] dp[i][1]代表不持有股票所得的最多现金。其中, i i i代表天数。假设最初的现金为 0 0 0,那么加入第 i i i天买入股票现金就是 − p r i c e s [ i ] -prices[i] prices[i](负数)。
  • 第二步,递推公式。 d p [ i ] [ 0 ] dp[i][0] dp[i][0]可以由两种情况得出:第 i − 1 i-1 i1天就持有股票了(只能买一次,之前买过),那么 d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] dp[i][0] = dp[i-1][0] dp[i][0]=dp[i1][0];第 i i i天买入股票,那么 d p [ i ] [ 0 ] = − p r i c e s [ i ] dp[i][0] = -prices[i] dp[i][0]=prices[i]。因为要获取最大利润,那么只能挑便宜的买(这两个值都是负数),故我们在二者之间取最大值: d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , − p r i c e s [ i ] ) dp[i][0] = max(dp[i - 1][0], -prices[i]) dp[i][0]=max(dp[i1][0],prices[i])。同理, d p [ i ] [ 1 ] dp[i][1] dp[i][1]也可以由两种情况得出:第 i − 1 i-1 i1天不持有股票(已经卖出或者还未买入),那么保持现状 d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] dp[i][1] = dp[i - 1][1] dp[i][1]=dp[i1][1];第 i i i天卖出股票,有 d p [ i ] [ 1 ] = p r i c e s [ i ] + d p [ i − 1 ] [ 0 ] dp[i][1] = prices[i] + dp[i - 1][0] dp[i][1]=prices[i]+dp[i1][0]。因为要挑贵的卖出,故取最大值: d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 1 ] , p r i c e s [ i ] + d p [ i − 1 ] [ 0 ] ) dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]) dp[i][1]=max(dp[i1][1],prices[i]+dp[i1][0])
  • 第三部,元素初始化。令 d p [ 0 ] [ 0 ] = − p r i c e s [ 0 ] dp[0][0] = -prices[0] dp[0][0]=prices[0] d p [ 0 ] [ 1 ] = 0 dp[0][1] = 0 dp[0][1]=0
  • 第四部,递归顺序。循环从 i = 1 i = 1 i=1开始。
  • 第五步,打印结果。最终必然是要卖出股票,状态是不持有股票,所以返回 d p [ p r i c e s . s i z e ( ) − 1 ] [ 1 ] dp[prices.size() - 1][1] dp[prices.size()1][1]

  程序如下

// 121、股票I-动态规划
class Solution {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) return 0;
		vector<vector<int>> dp(prices.size(), vector<int>(2));	// 二维数组,行代表天数,列代表是否持有股票
		dp[0][0] -= prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++) {
			dp[i][0] = max(dp[i - 1][0], -prices[i]);				// 第i天持有股票
			dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);	// 第i天不持有股票
		}
		return dp[prices.size() - 1][1];
	}
};

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

1.2 动态规划-滚动数组

  在上面程序的基础之上,我们发现对于 d p [ i ] [ j ] dp[i][j] dp[i][j]来说,只利用了 d p [ i − 1 ] [ j ] dp[i-1][j] dp[i1][j],因此空间不必开辟那么大。利用滚动数组,我们将空间复杂度降低到 O ( 1 ) O(1) O(1)
  程序如下

// 121、股票I-动态规划-滚动数组
class Solution2 {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) return 0;
		vector<vector<int>> dp(2, vector<int>(2));	// 二维数组,行代表天数,列代表是否持有股票
		dp[0][0] -= prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++) {
			dp[i % 2][0] = max(dp[(i - 1) % 2][0], -prices[i]);				// 第i天持有股票
			dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);	// 第i天不持有股票
		}
		return dp[(prices.size() - 1) % 2][1];
	}
};

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

二、122、买卖股票的最佳时机 II

在这里插入图片描述

  思路分析:本题与121题不同之处在于可以多次买卖,但是买入一只股票之前不能持有其他股票。因为这一点不一样,所以当第 i i i天买入股票的时候,所持有的现金可能有之前买卖过的利润。那么第 i i i天持有股票即 d p [ i ] [ 0 ] dp[i][0] dp[i][0],如果是第 i i i天买入股票,所得现金就是昨天不持有股票的所得现金减去今天的股票价格 即: d p [ i − 1 ] [ 1 ] − p r i c e s [ i ] dp[i - 1][1] - prices[i] dp[i1][1]prices[i]。其余部分的分析和121题完全一样。
  程序如下

// 122、股票II-动态规划
class Solution3 {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) return 0;
		vector<vector<int>> dp(prices.size(), vector<int>(2));	// 二维数组,行代表天数,列代表是否持有股票
		dp[0][0] -= prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++) {
			dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);	// 第i天持有股票
			dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);	// 第i天不持有股票
		}
		return dp[prices.size() - 1][1];
	}
};

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

  同理,本题也可以用滚动数组降低空间复杂度:

// 122、股票II-动态规划-滚动数组
class Solution4 {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) return 0;
		vector<vector<int>> dp(2, vector<int>(2));	// 二维数组,行代表天数,列代表是否持有股票
		dp[0][0] -= prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++) {
			dp[i % 2][0] = max(dp[(i - 1) % 2][0], dp[(i - 1) % 2][1] - prices[i]);	// 第i天持有股票
			dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);	// 第i天不持有股票
		}
		return dp[(prices.size() - 1) % 2][1];
	}
};

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

三、123、买卖股票的最佳时机 III

在这里插入图片描述
  思路分析:本题又是另外一个变体,最多可有完成两笔交易,同时买入一只股票之前不能持有其他股票。一天一共只有五个状态:1、没有操作;2、第一次持有股票;3、第一次不持有股票;4、第二次持有股票;5、第二次不持有股票。套用121题的思路,我们创建一个二维数组,行代表天数,列代表状态。

七、完整代码

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

// 121、股票I-动态规划
class Solution {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) return 0;
		vector<vector<int>> dp(prices.size(), vector<int>(2));	// 二维数组,行代表天数,列代表是否持有股票
		dp[0][0] -= prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++) {
			dp[i][0] = max(dp[i - 1][0], -prices[i]);				// 第i天持有股票
			dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);	// 第i天不持有股票
		}
		return dp[prices.size() - 1][1];
	}
};

// 121、股票I-动态规划-滚动数组
class Solution2 {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) return 0;
		vector<vector<int>> dp(2, vector<int>(2));	// 二维数组,行代表天数,列代表是否持有股票
		dp[0][0] -= prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++) {
			dp[i % 2][0] = max(dp[(i - 1) % 2][0], -prices[i]);				// 第i天持有股票
			dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);	// 第i天不持有股票
		}
		return dp[(prices.size() - 1) % 2][1];
	}
};

// 122、股票II-动态规划
class Solution3 {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) return 0;
		vector<vector<int>> dp(prices.size(), vector<int>(2));	// 二维数组,行代表天数,列代表是否持有股票
		dp[0][0] -= prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++) {
			dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);	// 第i天持有股票
			dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);	// 第i天不持有股票
		}
		return dp[prices.size() - 1][1];
	}
};

// 122、股票II-动态规划-滚动数组
class Solution4 {
public:
	int maxProfit(vector<int>& prices) {
		if (prices.size() == 0) return 0;
		vector<vector<int>> dp(2, vector<int>(2));	// 二维数组,行代表天数,列代表是否持有股票
		dp[0][0] -= prices[0];
		dp[0][1] = 0;
		for (int i = 1; i < prices.size(); i++) {
			dp[i % 2][0] = max(dp[(i - 1) % 2][0], dp[(i - 1) % 2][1] - prices[i]);	// 第i天持有股票
			dp[i % 2][1] = max(dp[(i - 1) % 2][1], prices[i] + dp[(i - 1) % 2][0]);	// 第i天不持有股票
		}
		return dp[(prices.size() - 1) % 2][1];
	}
};

int main() {
	vector<int> prices = { 7,1,5,3,6,4 };
	Solution s1;
	int result = s1.maxProfit(prices);
	cout << result << endl;
	system("pause");
	return 0;
}

end

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

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

相关文章

【科技素养题】少儿编程 蓝桥杯青少组科技素养题真题及解析第23套

少儿编程 蓝桥杯青少组科技素养题真题及解析第23套 1、英国计算机科学家艾伦图灵于 1950 年提出了著名的“图灵测试”,用于判断计算机是否具有智能。“图灵测试”是通过()的方法进行判断的 A、让两台计算机对话 B、让人类与计算机对话 C、给计算机出题 D、让计算机分辨图…

Logstash 7.7.1版本安装系统梳理

前言 上一篇文章介绍了 《ElasticSearch7.7.1集群搭建 & Kibana安装》&#xff0c;今天说一下 Logstash的安卓和配置&#xff1b; Logstash是一个开源的数据收集引擎&#xff0c;具有实时管道功能。它可以动态地将来自不同数据源的数据统一起来&#xff0c;并将数据标准化…

【数据结构】双向带头循环链表实现及总结

简单不先于复杂&#xff0c;而是在复杂之后。 文章目录 1. 双向带头循环链表的实现2. 顺序表和链表的区别 1. 双向带头循环链表的实现 List.h #pragma once #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <stdbool.h>typede…

Springboot-SpringCloud学习

文章目录 web项目开发历史 SpringBootSpring以及Springboot是什么微服务第一个Springboot项目配置如何编写 yaml自动装配原理集成 web开发&#xff08;业务核心&#xff09;集成 数据库 Druid分布式开发&#xff1a;Dubbo&#xff08;RPC&#xff09; zookeeperswagger&#x…

免费的ppt网站分享

前言 相信大学生们深有体会&#xff0c;对于学校而言&#xff0c;好像是任何活动都需要我们做ppt&#xff0c;当你拿着自己辛苦做的ppt去展示现场的时候&#xff0c;你看到别人的ppt比你的还好&#xff0c;此时心情就是毙&#xff0c;当你知道人家不过是仅仅的1个小时不到就完成…

Springboot集成Javamelody

JavaMelody的目标是监视QA和生产环境中的Java或Java EE应用服务器。它不是模拟用户请求的工具&#xff0c;而是根据用户对应用程序的使用情况来衡量和计算应用程序实际操作的统计信息的工具。JavaMelody主要基于请求统计和演化图。 它允许改进QA和生产中的应用程序&#xff0c…

海外云手机对于亚马逊卖家的作用

近年来&#xff0c;海外云手机作为一种新型模式迅速崭露头角&#xff0c;成为专业的出海SaaS平台软件。海外云手机在云端运行和存储数据&#xff0c;通过网页端操作&#xff0c;将手机芯片放置在机房&#xff0c;通过网络连接到服务器&#xff0c;为用户提供便捷的上网功能。因…

WebService的services.xml问题

WebService有多种实现方式&#xff0c;这里使用的是axis2 问题&#xff1a; 在本地开发&#xff0c;访问本地的http://localhost:8080/services/ims?wsdl&#xff0c;正常访问 但是打成jar包&#xff0c;不管是linux还是window启动&#xff0c;都访问不到&#xff0c;报错…

双创竞赛项目申报:Java + Spring Boot的实战指南

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

2024前端面试总结—JS篇(文档持续更新中。。。)

1、Event Loop&#xff08;事件循环&#xff09;机制 JS是单线程的非阻塞语言 为什么是单线程&#xff08;如果js是多线程&#xff0c;那么两个线程同时对同一个Dom进行操作&#xff0c;一个增一个删&#xff0c;浏览器该如何执行&#xff1f;&#xff09; 非阻塞&#xff08;…

如何线上发布寒假作业,让学生在线确认签收?

老师们可以利用易查分制作一个寒假作业查询系统&#xff0c;在线发布学生的寒假作业&#xff0c;让学生本人在线上获取寒假作业&#xff1b;如果希望由学生本人进行签收&#xff0c;还可通过手写签名功能来进行确认&#xff0c;确保由学生本人收到寒假作业。 &#x1f4cc;使用…

Java项目要不要部署在Docker里?

部署Java项目有很多种方式&#xff0c;传统的方式是直接在物理机或虚拟机上部署应用&#xff0c;但为什么现在容器化部署变得越来越流行&#xff0c; 个人觉得原因有以下几个&#xff1a; 1、 环境一致性&#xff1a;使用Docker可以确保开发、测试和生产环境的一致性&#xff…

管理的四种风格

前言 管理的四种风格,一般的领导大概就是这几种管理模式,告知,辅导,参与,授权,还有就是乱搞式(神经病模式)。 一、告知式 告知式是指组织通过正式、明确的渠道,将信息传达给员工。这种方式通常用于传递基本的规章制度、工作流程、政策文件等。告知式的作用在于确保员…

Yalmip学习笔记

这里写自定义目录标题 基本用法变量定义关于大MBilevel programming 注&#xff1a;这篇文章主要是留给自己查漏补缺的&#xff0c;所以从来没有使用过yalmip的读者看着会觉得跳来跳去。 基本用法 建模开始前&#xff0c;使用yalmip(clear)清空Yalmip的内部数据库。 下面是一个…

Win10+wsl2+mmdetection3d(GPU)

2024部署mmdetection3d在win10wsl2 实现过程安装wsl2安装docker与VSCode插件连接其他问题 实现过程 安装WSL2 踩坑点&#xff1a; 基于发行版安装&#xff0c;无法更新wsl1&#xff0c;查证了当前的wi10的驱动是满足要求的&#xff0c;但是无法更新。所以一定要先去更新驱动&…

【程序员英语】【美语从头学】初级篇(入门)(笔记)Lesson13(买东西)(餐厅点餐事宜;询问有无座位;食物如何调理:牛排、咖啡等;菜单等相关)

《美语从头学初级入门篇》 注意&#xff1a;被 删除线 划掉的不一定不正确&#xff0c;只是不是标准答案。 文章目录 Lesson 13 At the Restaurant 在餐厅会话A会话B笔记餐厅询问有无座位&#xff1b;餐厅电话订座其他餐厅询问有无座位的问法 吸烟区与非吸烟区&#xff08;smo…

序列化流 ObjectInputStream 和 ObjectOutputStream 的基本使用【 File类+IO流知识回顾④】

序列化流 ObjectInputStream 和 ObjectOutputStream 的基本使用【 File类IO流知识回顾④】 序列化流序列化和反序列化如何实现序列化ObjectOutputStreamObjectInputStream 序列化流 什么是序列化&#xff1f;如何实现序列化&#xff1f;什么是反序列化&#xff1f;需要了解的类…

蓝桥杯嵌入式——省赛模板构建

新建一个省赛模板文件夹,在里面存放上源工程和目标工程 打开STM32CubeMX新建工程 选择芯片为STM32G431RBT6 CubeMX配置时钟系统 NVIC中断优先级分组为组4 RCC的高速时钟配置为晶振

【AI视野·今日Robot 机器人论文速览 第七十七期】Mon, 15 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Mon, 15 Jan 2024 Totally 14 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Learning Joint Space Reference Manifold for Reliable Physical Assistance Authors Amirreza Razmjoo, Tilen Brecelj, Kri…

SpringClound项目相关

nacos本机模式非虚拟机启动也可正常连接 nacos中的配置中心相当于在application.yml中的相关配置&#xff0c;转移位置&#xff0c;内容同application.yml完全一样均可。 黑马项目导入后&#xff0c;依赖缺失&#xff1a; 首先尝试maven重新加载&#xff0c;控制台提示传递依…