Leetcode经典题6--买卖股票的最佳时机

买卖股票的最佳时机

题目描述:

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

输入输出示例:

输入:[7,1,5,3,6,4]

输出:5

解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

解题方案:

方式一:暴力求解(不推荐)

算法思路:最低买入,最高卖出 我们需要找出给定数组中两个数字之间的最大差值(即,最大利润)。此外,第二个数字(卖出价格)必须大于第一个数字(买入价格)。

形式上,对于每组 i 和 j(其中 j>i)我们需要找出 max(prices[j]−prices[i])。

实现代码

public class Solution {public int maxProfit(int[] prices) {int maxprofit = 0;//i指向买入时的价格for (int i = 0; i < prices.length - 1; i++) {//j指向卖出时的价格for (int j = i + 1; j < prices.length; j++) {//求出利润int profit = prices[j] - prices[i];if (profit > maxprofit) {maxprofit = profit;}}}return maxprofit;}
}

复杂度分析

时间复杂度:O(n2)。二重循环,循环运行 2n(n−1)​ 次。

空间复杂度:O(1)。只使用了常数个变量。

方法二:一次遍历

算法思想:假设给定的数组为:[7, 1, 5, 3, 6, 4]

如果我们在图表上绘制给定数组中的数字,我们将会得到:

如果自己购买股票,每天肯定会想:如果股票在历史最低点卖出就好了

因此,用变量记录历史最低点,同时计算自己的股票在第i天卖出能够获得的利润,每天都不断地更新这两个变量,从而可以在遍历一次数组的情况下,就可以获得最大利润

class Solution {public int maxProfit(int[] prices) {//初始化变量,最大利润ans为0,默认第一天prices[0]为股票最低价格买入int ans=0,minPrice=prices[0];//遍历传入的数组prices中的每个元素,并把当前元素赋值给变量pfor(int p:prices){//更新最大利润;计算当前卖出去价格p减去之前的最低买入价格minPrice的利润;与之前获取的利润ans比较,获取最大利润ans=Math.max(ans,p-minPrice);//更新最低买入价格,采用当前价格p和之前的最低价minPrice中较小的一个minPrice=Math.min(minPrice,p);}return ans;//返回最大利润
}
}

买卖股票的最佳时机 进阶版

题目描述

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。可以在一段时间内买卖多张股票

返回 你能获得的 最大利润 。

输入输出示例

输入:prices = [7,1,5,3,6,4]

输出:7

解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。最大总利润为 4 + 3 = 7 。

解题方案

方式一:动态规划

算法思想:

定义状态

dp[i][0] 表示第 i 天交易完后手里没有股票的最大利润,

dp[i][1] 表示第 i 天交易完后手里持有一支股票的最大利润(i 从 0 开始)。

如果这一天交易完后手里没有股票,考虑 dp[i][0] 的值会有两种情况:

  • 前一天已经没有股票,即 dp[i−1][0],
  • 前一天结束的时候手里持有一支股票,即 dp[i−1][1],这时候我们要将其卖出,并获得 prices[i] 的收益。

如果这一天交易完后手里有股票,考虑 dp[i][1] 的值会有两种情况:

  • 前一天已经持有一支股票,即 dp[i−1][1]
  • 前一天结束时还没有股票,即 dp[i−1][0],这时候我们要将其买入,并减少 prices[i] 的收益。

初始条件可以由计算得到 dp[0][0]=0,dp[0][1]=−prices[0]。

由于全部交易结束后,持有股票的收益一定低于不持有股票的收益,因此这时候 dp[n−1][0] 的收益必然是大于 dp[n−1][1] 的,最后的答案即为 dp[n−1][0]。

每一天的状态只与前一天的状态有关,而与更早的状态都无关,因此我们不必存储这些无关的状态,只需要将 dp[i−1][0] 和 dp[i−1][1] 存放在两个变量中,通过它们计算出 dp[i][0] 和 dp[i][1] 并存回对应的变量,以便于第 i+1 天的状态转移即可。

实现代码

class Solution {public int maxProfit(int[] prices) {int n = prices.length;//初始化int dp0 = 0, dp1 = -prices[0];for (int i = 1; i < n; ++i) {//对于每一天,都计算出持有股票的收益和未持有股票的收益,不断地进行迭代int newDp0 = Math.max(dp0, dp1 + prices[i]);int newDp1 = Math.max(dp1, dp0 - prices[i]);dp0 = newDp0;dp1 = newDp1;}return dp0;}
}
方法二:贪心

算法思想:由于股票的购买没有限制,因此整个问题等价于寻找 x 个不相交的区间 (li,ri​] 使得如下的等式最大化

其中 li​ 表示在第 li​ 天买入,ri​ 表示在第 ri​ 天卖出。

 

如图所示,如果第i天的价格高于第i-1天的价格,则将利润加入到总利润当中

需要说明的是,贪心算法只能用于计算最大利润,计算的过程并不是实际的交易过程

实现代码:

class Solution {public int maxProfit(int[] prices) {int ans = 0;int n = prices.length;for (int i = 1; i < n; ++i) {ans += Math.max(0, prices[i] - prices[i - 1]);}return ans;}
}

复杂度分析

时间复杂度:O(n),其中 n 为数组的长度。我们只需要遍历一次数组即可。

空间复杂度:O(1)。只需要常数空间存放若干变量。

欢迎大家点赞,评论加收藏

 

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

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

相关文章

MCPTT 与BTC

MCPTT&#xff08;Mission Critical Push-to-Talk&#xff09;和B-TrunC&#xff08;宽带集群&#xff09;是两种关键通信标准&#xff0c;它们分别由不同的组织制定和推广。 MCPTT&#xff08;Mission Critical Push-to-Talk&#xff09;标准由3GPP&#xff08;第三代合作伙伴…

去除账号密码自动赋值时的输入框背景色

问题描述&#xff1a; 前端使用账号密码登录&#xff0c;若在网页保存过当前页面的密码和账号&#xff0c;那么当再次进入该页面&#xff0c;网页会自动的把账号和密码赋到输入框中&#xff0c;而此时输入框是带有背景色的&#xff0c;与周边的白色背景显得很不协调&#xff1…

【Pytorch】torch.reshape与torch.Tensor.reshape区别

问题引入&#xff1a; 在Pytorch文档中&#xff0c;有torch.reshape与torch.Tensor.reshape两个reshape操作&#xff0c;他们的区别是什么呢&#xff1f; 我们先来看一下官方文档的定义&#xff1a; torch.reshape&#xff1a; torch.Tensor.reshape: 解释&#xff1a; 在p…

扫码与短信验证码登录JS逆向分析与Python纯算法还原

文章目录 1. 写在前面2. 扫码接口分析2. 短信接口分析3. 加密算法还原【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!…

spring6:3容器:IoC

spring6&#xff1a;3容器&#xff1a;IoC 目录 spring6&#xff1a;3容器&#xff1a;IoC3、容器&#xff1a;IoC3.1、IoC容器3.1.1、控制反转&#xff08;IoC&#xff09;3.1.2、依赖注入3.1.3、IoC容器在Spring的实现 3.2、基于XML管理Bean3.2.1、搭建子模块spring6-ioc-xml…

【认证法规】安全隔离变压器

文章目录 定义反激电源变压器 定义 安全隔离变压器&#xff08;safety isolating transformer&#xff09;&#xff0c;通过至少相当于双重绝缘或加强绝缘的绝缘使输入绕组与输出绕组在电气上分开的变压器。这种变压器是为以安全特低电压向配电电路、电器或其它设备供电而设计…

车机端同步outlook日历

最近在开发一个车机上的日历助手&#xff0c;其中一个需求就是要实现手机端日历和车机端日历数据的同步。然而这种需求似乎没办法实现&#xff0c;毕竟手机日历是手机厂商自己带的系统应用&#xff0c;根本不能和车机端实现数据同步的。 那么只能去其他公共的平台寻求一些机会&…

OpenCV-图像阈值

简单阈值法 此方法是直截了当的。如果像素值大于阈值&#xff0c;则会被赋为一个值&#xff08;可能为白色&#xff09;&#xff0c;否则会赋为另一个值&#xff08;可能为黑色&#xff09;。使用的函数是 cv.threshold。第一个参数是源图像&#xff0c;它应该是灰度图像。第二…

力扣300.最长递增子序列

题目描述 题目链接300. 最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 […

Vue CLI的作用

Vue CLI&#xff08;Command Line Interface&#xff09;是一个基于Vue.js的官方脚手架工具&#xff0c;其主要作用是帮助开发者快速搭建Vue项目的基础结构和开发环境。以下是Vue CLI的具体作用&#xff1a; 1、项目模板与快速生成 Vue CLI提供了一系列预设的项目模板&#x…

【蓝桥杯每日一题】扫雷

扫雷 知识点 2024-12-3 蓝桥杯每日一题 扫雷 dfs &#xff08;bfs也是可行的&#xff09; 题目大意 在一个二维平面上放置这N个炸雷&#xff0c;每个炸雷的信息有$(x_i,y_i,r_i) $&#xff0c;前两个是坐标信息&#xff0c;第三个是爆炸半径。然后会输入M个排雷火箭&#xff0…

【大数据学习 | 面经】Spark 3.x 中的AQE(自适应查询执行)

Spark 3.x 中的自适应查询执行&#xff08;Adaptive Query Execution&#xff0c;简称 AQE&#xff09;通过多种方式提升性能&#xff0c;主要包括以下几个方面&#xff1a; 动态合并 Shuffle 分区&#xff08;Coalescing Post Shuffle Partitions&#xff09;&#xff1a; 当 …

城电科技 | 光伏景观长廊 打造美丽乡村绿色低碳示范区 光伏景观设计方案

光伏景观长廊是一种结合了光伏发电技术和零碳景观设计的新型公共公共设施&#xff0c;光伏景观长廊顶上的光伏板不仅可以为周边用电设备提供清洁电能&#xff0c;而且还能作为遮阳设施使用&#xff0c;为人们提供一个美丽又实用的休闲娱乐空间。 光伏景观长廊建设对打造美丽乡…

开发系统准备与开发环境配置总结

开发前系统配置及环境搭建 系统配置0 Github打不开、速度慢怎么办1 WSL、Linux、Ubuntu、Docker都是什么鬼2 在Windows下安装WSL和Ubuntu3 配置MySQL4 配置Redis并启动服务5 Docker&#xff08;Windows和Ubuntu下&#xff09;6 Nginx 系统配置 你好&#xff01; 这是你第一次使…

uniapp 添加loading

在uniapp中添加loading可以使用uni的API uni.showLoading 方法。以下是一个简单的示例代码 // 显示loading uni.showLoading({title: 加载中 });// 假设这里是异步操作&#xff0c;比如网络请求 setTimeout(function () {// 隐藏loadinguni.hideLoading(); }, 2000);

C++(九)

前言&#xff1a; 本文主要讲述运算符的优先顺序。 一&#xff0c;运算符的优先级。 请看以下表达式&#xff1a; a32*5 运算结果为&#xff1a;13. 可以看到&#xff0c;在此代码中&#xff0c;先运行了2*5的结果&#xff0c;在此基础上在进行3操作&#xff0c;因此结果…

Android 拍照(有无存储权限两种方案,兼容Q及以上版本)

在某些行业&#xff0c;APP可能被禁止使用存储权限&#xff0c;或公司在写SDK功能&#xff0c;不方便获取权限 所以需要有 无存储权限拍照方案。这里两种方案都列出里。 对于写入权限&#xff0c;在高版本中&#xff0c;已经废弃&#xff0c; 不可用文件写入读取权限&#xf…

【Altium Designer 】AD如何使用嘉立创元器件的3D封装

1.下载3D封装 以STM32F407VGT6为例&#xff0c;进入嘉立创商城网站&#xff0c;找到需要的元器件封装 复制编号&#xff0c;打开嘉立创EDA&#xff0c;编译器选择专业版&#xff0c;新建工程&#xff0c;点击PCB1 复制编号在搜索框中&#xff0c;点击搜索&#xff0c;然后放置…

爬虫运行后数据如何存储?

爬虫运行后获取的数据可以存储在多种不同的存储系统中&#xff0c;具体选择取决于数据的规模、查询需求以及应用场景。以下是一些常见的数据存储方法&#xff1a; 1. 文件系统 对于小型项目或临时数据存储&#xff0c;可以直接将数据保存到本地文件中。常见的文件格式包括&…

【机器学习】机器学习的基本分类-监督学习-梯度提升树(Gradient Boosting Decision Tree, GBDT)

梯度提升树是一种基于**梯度提升&#xff08;Gradient Boosting&#xff09;**框架的机器学习算法&#xff0c;通过构建多个决策树并利用每棵树拟合前一棵树的残差来逐步优化模型。 1. 核心思想 Boosting&#xff1a;通过逐步调整模型&#xff0c;使后续的模型重点学习前一阶段…