春招第一步,算法伴我行
题目描述
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
如:[7,1,5,3,6,4],最大利润为6-1=5.
思路
动态规划题目。
当前状态是什么?上一状态和当前状态有什么关系?怎么由上一状态推出当前状态?从这三个方面来回答。
- 当前状态:
肯定是我当前的股票价格对应的利润。一个变量表示状态够吗?不够。。。为什么不够呢?由于只能进行一次买卖,因此设计到你是否使用当前的股票之前,你到底还能不能进行交易。因此还需要开辟一个变量来进行状态的二维定义:对于当前的股票,我所对应的状态是否允许我再进行操作。
思考一下:我所对应的状态有哪些?由于只能进行一次交易,自然能想到:可以交易、不能交易两种状态。但是我们引申一下(其实两种状态已经足够,待会分析),可以交易是什么意思?是还没进行一次的前提下可以买入?还是已经买入只能卖出??因此状态有三个:当前股票下,我还没有进行任何操作dp[i][0]
,我可以买入:dp[i][1]
,我已经买入,只能卖出了dp[i][2]
三种状态。 - 上一状态
当前状态和上一状态是一样的。只不过需要注意最初是状态:dp[0][0]=0, dp[0][1]=-nums[0], dp[0][2]=0
。 - 上一状态和当前状态有嘛关系
还是从当前的三个状态来看:dp[i][0]
:一次操作都没进行所对应的最大利润,当然,上一状态也是什么都没进行,两个状态是一样的:dp[i][0]=dp[i-1][0]
;dp[i][1]
:已经买进股票对应的最大利润,上一状态有两种可能:dp[i-1][0]
:即我上一状态什么都没做,那自然是第i次进行了买入,利润为dp[i-1][0]+prices[i]
;dp[i-1][1]
:第i-1次已经买入,第i次什么都没做,对应的利润是dp[i-1][1]
,因此,dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i]
(考虑了股票价可能为负);dp[i][2]
:和dp[i][1]
类似,dp[i][2] = max(dp[i-1][2], dp[i-1][1]+prices[i]
。
代码
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if not prices:return 0
dp = [[0]*3 for _ in range(len(prices))]
dp[0][0], dp[0][1], dp[0][2] = 0, -prices[0], 0
for i in range(1, len(prices)):
dp[i][0] = dp[i-1][0]
dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i])
dp[i][2] = max(dp[i-1][2], dp[i-1][1]+prices[i])
return dp[-1][2]
太啰嗦了,其中有个状态从头到尾就没有使用:dp[i][0]==0
,简化一下:
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if not prices:return 0
dp = [[0]*2 for _ in range(len(prices))]
dp[0][0], dp[0][1] = -prices[0], 0
for i in range(1, len(prices)):
dp[i][0] = max(dp[i-1][0], 0-prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0]+prices[i])
return dp[-1][1]
其实有个很简单的思路去解决:两个变量:最低价格和最大利润。从头遍历,先计算利润,只要是最大,更新最大利润。如果当前价格是最低价格,更新最低价格。
class Solution:
def maxProfit(self, prices):
"""
:type prices: List[int]
:rtype: int
"""
if not prices:return 0
buy_price, profit = prices[0], 0
for x in prices[1:]:
if x<buy_price:
buy_price = x
if x-buy_price>profit:
profit = x-buy_price
return profit