字节跳动面试题.股票交易问题系列 「leetcode121、leetcode122、leetcode123、leetcode188、leetcode309 、leetcode714」
目录
题目一
1.「leetcode121,一次买卖」
2. 解题思路
3.代码实现
题目二
1.「leetcode122,多次买卖」
2. 解题思路
3.代码实现
题目三
1.「leetcode123,最多两次买卖」
2.解题思路
3.代码实现
题目四
1.「leetcode188,最多k次买卖」
2.解题思路
3.代码实现
题目五
1.「leetcode309,多次买卖含冷冻期」
2.解题思路
3.代码实现
题目六
1.「leetcode714,多次买卖含手续费」
2.解题思路
3.代码实现
题目一
1.「leetcode121,一次买卖」
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
2. 解题思路
以卖出那天 i 的股票价格为基准nums[i],找到 i 之前的那些天中最小的买入值minv,最小值不需要另外的数组保存,利用minv=min(minv,nums[i])更新,res=max(res,nums[i]-minv)即为所求
思路二:
3.代码实现
class Solution(object):def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""if not prices:return 0minv=prices[0]res=0for i in range(len(prices)):res=max(res,prices[i]-minv)minv=min(minv,prices[i])return res
题目二
1.「leetcode122,多次买卖」
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
2. 解题思路
贪心算法,一次遍历,只要今天价格小于明天价格就在今天买入然后明天卖出
[7, 1, 5, 6]
第二天买入,第四天卖出,收益最大(6-1),所以一般人可能会想,怎么判断不是第三天就卖出了呢? 这里就把问题复杂化了,根据题目的意思,当天卖出以后,当天还可以买入,所以其实可以第三天卖出,第三天买入,第四天又卖出((5-1)+ (6-5) === 6 - 1)。所以算法可以直接简化为只要今天比昨天大,就卖出。
3.代码实现
class Solution(object):def maxProfit(self, prices):profit = 0for day in range(len(prices)-1):differ = prices[day+1] - prices[day]if differ > 0:profit += differreturn profit
题目三
1.「leetcode123,最多两次买卖」
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [3,3,5,0,0,3,1,4]
输出: 6
解释: 在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
示例 2:输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:输入: [7,6,4,3,1]
输出: 0
解释: 在这个情况下, 没有交易完成, 所以最大利润为 0。
2.解题思路
利用「状态」进行穷举
每天都有三种「选择」:买入、卖出、无操作,我们用 buy,sell,rest 表示这三种选择。但问题是,并不是每天都可以任意选择这三种选择的,因为 sell 必须在 buy之后,buy 必须在 sell 之后。那么 rest 操作还应该分两种状态,一种是 buy 之后的 rest(持有了股票),一种是 sell 之后的 rest(没有持有股票)。而且别忘了,我们还有交易次数 max_k(此题 max_k=2 )的限制,就是说你 buy 还只能在 k > 0 的前提下操作。
这个问题的「状态」有三个,第一个是天数,第二个是允许交易的最大次数,第三个是当前的持有状态(即之前说的 rest 的状态,我们不妨用 1 表示持有,0 表示没有持有)
for 1 <= i <= n:for 1 <= k <= max_k:for s in {0, 1}:dp[i][k][s] = max(buy, sell, rest)
dp[3][2][1] 的含义:今天是第三天,我现在手上持有着股票,至今最多进行 2 次交易。
dp[2][3][0] 的含义:今天是第二天,我现在手上没有持有股票,至今最多进行 3 次交易。
我们想求的最终答案是 dp[n][max_k][0]
,即最后一天,最多允许 max_k 次交易,最多获得多少利润。
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])max( 选择 rest , 选择 sell )解释:今天我没有持有股票,有两种可能:
要么是我昨天就没有持有,然后今天选择 rest,所以我今天还是没有持有;
要么是我昨天持有股票,但是今天我 sell 了,所以我今天没有持有股票了。dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])max( 选择 rest , 选择 buy )解释:今天我持有着股票,有两种可能:
要么我昨天就持有着股票,然后今天选择 rest,所以我今天还持有着股票;
要么我昨天本没有持有,但今天我选择 buy,所以今天我就持有股票了。
如果 buy,就要从利润中减去 prices[i],如果 sell,就要给利润增加 prices[i]。今天的最大利润就是这两种可能选择中较大的那个。而且注意 k 的限制,我们在选择 buy 的时候,把 k 减小了 1,这里不可以在 sell 的时候减 1,必须在buy的时候减去1,因为交易最开始发生在buy期间。
最后,初始状态:
dp[0][k][0] = 0
解释:第0天,从第1天开始交易,现在还没交易,利润当然是 0 。
dp[0][k][1] = -infinity
解释:还没开始的时候,是不可能持有股票的,用负无穷表示这种不可能。
dp[i][0][0] = 0
解释:因为 k 是从 1 开始的,所以 k = 0 最多允许0次交易,不允许交易,这时候利润当然是 0 。
dp[i][0][1] = -infinity
解释:不允许交易的情况下,是不可能持有股票的,用负无穷表示这种不可能。
总结:
base case:
dp[0][k][0] = dp[i][0][0] = 0
dp[0][k][1] = dp[i][0][1] = -infinity状态转移方程:
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
关于base case的实现:
for k in range(max_k+1):dp[0][k][0] = 0dp[0][k][1] = -sys.maxsizefor i in range(n+1):dp[i][0][0] = 0dp[i][0][1] = -sys.maxsize
3.代码实现
import sys
class Solution(object):def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""if not prices:return 0max_k=2n=len(prices)dp=[[[0 for _ in range(2)] for _ in range(max_k+1) ] for _ in range(n+1)]for k in range(max_k+1):dp[0][k][0]=0dp[0][k][1]=-sys.maxsizefor i in range(n+1):dp[i][0][0]=0dp[i][0][1]=-sys.maxsizefor i in range(1,n+1):for k in range(max_k,0,-1):dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][k][1]+prices[i-1])dp[i][k][1]=max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i-1])return dp[n][max_k][0]
题目四
1.「leetcode188,最多k次买卖」
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。
注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [2,4,1], k = 2
输出: 2
解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
示例 2:输入: [3,2,6,5,0,3], k = 2
输出: 7
解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
2.解题思路
有了上一题 max_k = 2 的铺垫,这题应该和上一题的第一个解法没啥区别。但是出现了一个超内存的错误,原来是传入的 k 值会非常大,dp 数组太大了。现在想想,交易次数 k 最多有多大呢?
一次交易由买入和卖出构成,至少需要两天。所以说有效的限制 k 应该不超过 n/2,如果超过,就没有约束作用了,相当于 k = +infinity。这种情况是之前解决过的。
3.代码实现
直接把之前的代码重用
class Solution(object):def maxProfit_1(self, prices):profit = 0for day in range(len(prices)-1):differ = prices[day+1] - prices[day]if differ > 0:profit += differreturn profitdef maxProfit(self, k, prices):""":type k: int:type prices: List[int]:rtype: int"""if not prices:return 0max_k=kn=len(prices)if max_k> n//2:return self.maxProfit_1(prices)dp=[[[0 for _ in range(2)] for _ in range(max_k+1) ] for _ in range(n+1)]for k in range(max_k+1):dp[0][k][0]=0dp[0][k][1]=-sys.maxsizefor i in range(n+1):dp[i][0][0]=0dp[i][0][1]=-sys.maxsizefor i in range(1,n+1):for k in range(max_k,0,-1):dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][k][1]+prices[i-1])dp[i][k][1]=max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i-1])return dp[n][max_k][0]
题目五
1.「leetcode309,多次买卖含冷冻期」
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
2.解题思路
如果 k 为正无穷,那么就可以认为 k 和 k - 1 是一样的。可以这样改写框架:
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
= max(dp[i-1][k][1], dp[i-1][k][0] - prices[i])
我们发现数组中的 k 已经不会改变了,也就是说不需要记录 k 这个状态了:
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])
如果有冷冻期,每次 sell 之后要等一天才能继续交易。只要把这个特点融入上面的状态转移方程即可:
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-2][0] - prices[i])
解释:第 i 天选择 buy 的时候,要从 i-2 的状态转移,而不是 i-1 。
3.代码实现
import sys
class Solution(object):def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""if not prices:return 0n=len(prices)dp=[[0 for _ in range(2)] for _ in range(n+1)]dp[0][0] = 0dp[0][1] = -sys.maxsizefor i in range(1,n+1):dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i-1])dp[i][1]=max(dp[i-1][1],dp[i-2][0]-prices[i-1])return dp[n][0]
题目六
1.「leetcode714,多次买卖含手续费」
给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。
你可以无限次地完成交易,但是你每次交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。
返回获得利润的最大值。
示例 1:
输入: prices = [1, 3, 2, 8, 4, 9], fee = 2
输出: 8
解释: 能够达到的最大利润:
在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
注意:0 < prices.length <= 50000.
0 < prices[i] < 50000.
0 <= fee < 50000.
2.解题思路
每次交易要支付手续费,参考题目五中无限次交易的状态转移公式,只要把手续费从利润中减去即可。改写方程:
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)
解释:相当于买入股票的价格升高了。在第一个式子里减也是一样的,相当于卖出股票的价格减小了。
3.代码实现
import sys
class Solution(object):def maxProfit(self, prices, fee):""":type prices: List[int]:rtype: int"""if not prices:return 0n=len(prices)dp=[[0 for _ in range(2)] for _ in range(n+1)]dp[0][0] = 0dp[0][1] = -sys.maxsizefor i in range(1,n+1):dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i-1])dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i-1]-fee)return dp[n][0]
参考出处
作者:labuladong
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/solution/yi-ge-tong-yong-fang-fa-tuan-mie-6-dao-gu-piao-wen/
字节跳动面试题.股票交易问题系列 「leetcode121、leetcode122、leetcode123、leetcode188、leetcode309 、leetcode714」相关推荐
- 编程实践系列: 字节跳动面试题
字节跳动面试题 面试3轮技术面+1轮HR 整体分三大块: 项目经验 计算机基础 编程题(每轮一题) 项目经验 架构+业务 做了什么核心设计优化 解决了什么难题 体现思考 业务理解 架构设计能力 项目需 ...
- 最新字节跳动面试题与岗位层级,绩效考核制度介绍
最新字节跳动面试题与岗位层级,绩效考核制度介绍 1.算法题一:无序数组的中位数 (快排思想O(N) 时间复杂度) 2.算法题二:给一数组,让你找一对满足i 3.算法题三: 给一数组,让你找一对满足i& ...
- 最新字节跳动面试题与答案: 无序数组的中位数 (快排思想O(N) 时间复杂度)
最新字节跳动面试题与答案 1.算法题一:无序数组的中位数 (快排思想O(N) 时间复杂度) package com.lightsword.leetcodeproblemsimport org.juni ...
- 字节跳动java笔试题目_牛客网--字节跳动面试题--特征提取
牛客网--字节跳动面试题--特征提取 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 来源 链接:特征提取 来源:牛客网 题目 ...
- 牛客网--字节跳动面试题--雀魂启动
牛客网--字节跳动面试题--雀魂启动 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 来源 链接:雀魂启动 来源:牛客网 题目 ...
- 2018 java 字节跳动笔试题
想进字节跳动同学注意了,这里是修真院面试笔记整理,那么这里就给大家分享一下 [2018 java 字节跳动笔试题] 一面 实现算法:求全排列. 输入:一个整数n 输出:从1至n所有数字组成的全排列 简 ...
- 【字节跳动面试题】赛马问题 64匹马8个跑道最少几次赛出最快的4匹马
2020年1月 字节跳动研发岗实习面试题 文章目录 赛马问题 一. 64匹马8个跑道 二. 36匹马6赛道 赛马问题 一. 64匹马8个跑道 64匹马8个跑道(不计时),问最少要比多少次,才能知道最快 ...
- 2020年字节跳动面试题
字节跳动一面面试题: 自我介绍 聊聊项目,时间大概15种左右,面试官会根据项目的一些设计点来提问,提前做好准备,别自己坑了自己 分布式锁是锁住一部分还是整个系统,既然是锁住整个,为什么不用消息队列? ...
- 字节跳动和美团为什么都在「变硬」
为什么两个互联网公司分别开始在 VR.无人机方向上做如此坚决的投入? 字节收购 Pico 或高达 90 亿,要做元宇宙? [新闻回顾] 字节跳动收购国内 VR 行业出货量最大的厂商 Pico.由于收购 ...
最新文章
- 《构建之法》阅读笔记07
- python游戏程序-python游戏程序
- 智能算法之Matlab实现(1)——遗传算法(1)
- Vscode解决Setting.json报警告:Problems loading reference ... Unable to load schema from ...
- 8 list切片_Python中14个切片操作,你常用哪几个?
- geek_How-To Geek正在寻找安全作家
- 工业和信息化部办公厅关于公布2021年产业技术基础公共服务平台复核结果的通知
- 哎呀,搬运blog好累啊,96篇呢QwQ
- SQL Server存储过程中使用表值作为输入参数示例
- 血泪安装caffe教程
- 基于易智瑞(ArcGIS)JavaScript API的视频融合探索
- Android Studio制作简易音乐盒
- 【Unity问题】Int类型除法运算为什么归零
- 分布式系统之-我的书单
- 抢红包 作者 陈越单位 浙江大学
- 上年龄的笔记本升级固态硬盘和内存经验谈
- 磁盘块管理器DiskBlockManager
- elementui 点击按钮(文字) 预览图片
- IP 基础知识“全家桶”,45 张图一套带走
- 软考软件评测师备考攻略
热门文章
- 多线程和单线程有什么本质区别
- Java字符全半角转换
- 开博第一天,我的学习宣言
- 寻找COVID-19疗法:又一种需要治疗免疫老化的疾病
- 音频功率放大器LTK5135M,单声道1.2W~3.3W,PIN替换NS4150B/LPA2010/CS8302/CS8120M/IS31QP2005/IS31QP2006/BL6306/HT6873
- Oracle EBS GL获得货币汇率
- 理解Elasticsearch中的桶聚合(Bucket aggregation)
- chainer-图像分类-整体结构设计【附源码】
- strncat函数说明及模拟实现
- 华为od机考题目-停车位问题