给定一个数组 prices
,它的第 i
个元素 prices[i]
表示一支给定股票第 i
天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0
。
示例 1:
输入:[7,1,5,3,6,4] 输出:5 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
输入:prices = [7,6,4,3,1] 输出:0 解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
思路:选择某一天买入,然后再从这一天之和的某一天卖出,并且卖出的价格一定要大于买入的价格,因此利润最小设置为0,然后遍历prices数组,假设当天买入,然后在今天之后的某一天选择价格最高的那天卖出,得到一个利润,和已有的profit比较,直到遍历完数组。
代码(Python):
class Solution(object):
def maxProfit(self, prices):
profit = 0 #最大利润
for i in range(len(prices)):
buyPrice = prices[i] #买入价格
sellPrice = max(prices[i:len(prices)]) #从剩余几天选择一天价格最高的卖出
profit = max(profit,sellPrice-buyPrice) #更新profit
return profit
更新:上述的方法是最直观的,但时间复杂度很高,下面再给出贪心和动规的方法
贪心:遍历数组,每次都从左边取最小,作为买入的那天,然后计算卖掉能获得的最大利润,和上面的思路一样,但写法不同,时间复杂度也更小一些。
class Solution(object):
def maxProfit(self, prices):
result = 0
low = 100001
for i in range(len(prices)):
low = min(low,prices[i]) #最低买入价格
result = max(result,prices[i]-low) #能获得的最大利润
return result
动态规划:股票问题也是很经典的动规问题。
首先明确定义:dp[i][0]表示第i天持有股票所得的最大利润,dp[i][1]表示第i天不持有股票获得的最大利润;
然后递推公式:首先是dp[i][0]的,第i天持有股票可以分两种情况:1. 第i-1天就持有股票了,那dp[i][0] = dp[i-1][0],2.第i-1天没有股票,在第i天买入了股票,那dp[i][0] = -prices[i],一开始拥有的钱视为0,就等于减去买这支股票的钱。接下去是dp[i][1]的,第i天不持有股票也可以分为两种情况:1.第i-1天也不持有股票,dp[i][1] = dp[i-1][1],2.第i天把股票卖出了,那dp[i][1]=dp[i-1][0]+prices[i],等于前一天持有股票已得的利润加上卖出这支股票的钱。
然后是初始化:每个dp[i]依赖于dp[i-1]的值,因此dp[0][0]和dp[0][1]都需要初始化,dp[0][0]表示第0天持有股票,那就等于-prices[0],dp[0][1]表示第0天不持有股票,那就为0。
最后是遍历顺序,很明显从前往后遍历。
class Solution(object):
def maxProfit(self, prices):
dp = [[0]*2 for _ in range(len(prices) )]
if len(prices) == 0:
return 0
dp[0][0] = -prices[0]
dp[0][1] = 0
for i in range(1,len(prices)):
dp[i][0] = max(dp[i-1][0],-prices[i])
dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i])
return dp[len(prices)-1][1]