淘先锋技术网

首页 1 2 3 4 5 6 7

买卖股票的最佳时间 I

题目
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。
示例:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

// time:O(n)   space:O(1)
class Solution:
	def maxProfit(self,prices):
		n=len(prices)
		if n==0:return 0
		dp=[0]*n
		minprice=prices[0]
		for i in range(n):
			minprice=min(minprice,prices[i])
			dp[i]=max(prices[i]-minprice,dp[i-1])
		return dp[-1]

买卖股票最佳时机 II

题目
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
示例:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第2天(股票价格 = 1)的时候买入,在第3天(股票价格=5)的时候卖出, 这笔交易所能获得利润=5-1=4 。
随后,在第4天(股票价格=3)的时候买入,在第5天(股票价格=6)的时候卖出, 这笔交易所能获得利润=6-3=3 。

方法一(贪心算法)
算法流程

  • 遍历整个股票交易日价格列表 price,策略是所有上涨交易日都买卖(赚到所有利润),所有下降交易日都不买卖(永不亏钱)。
  1. 设 tmp 为第 i-1 日买入与第 i 日卖出赚取的利润,即 tmp = prices[i] - prices[i - 1] ;
  2. 当该天利润为正 tmp > 0,则将利润加入总利润 profit;当利润为 00 或为负,则直接跳过;
  3. 遍历完成后,返回总利润 profit。
// time:O(n)    space:O(1)
class Solution:
	def maxProfit(self,prices):
		n=len(prices)
		profit=0
		for i in range(1,n):
			temp=prices[i]-prices[i-1]
			if temp>0:
				profit+=temp
		return profit

方法二(动态规划)
第一步:定义状态
状态dp[i][j]定义如下:

  • 第一维 i 表示索引为 i 的那一天(具有前缀性质,即考虑了之前天数的收益)能获得的最大利润;
  • 第二维 j 表示索引为 i 的那一天是持有股票,还是持有现金。这里 0 表示持有现金(cash),1 表示持有股票(stock)。

第二步:思考状态转移方程

  • 状态从持有现金(cash)开始,到最后一天我们关心的状态依然是持有现金(cash);
  • 每一天状态可以转移,也可以不动。状态转移用下图表示:
    在这里插入图片描述
    说明:
  • 因为不限制交易次数,除了最后一天,每一天的状态可能不变化,也可能转移;
  • 写代码的时候,可以不用对最后一天单独处理,输出最后一天,状态为 0 的时候的值即可。

第3步:确定起始
起始的时候:

  • 如果什么都不做,dp[0][0] = 0;
  • 如果买入股票,当前收益是负数,即 dp[0][1] = -prices[i];

第4步:确定终止
终止的时候,上面也分析了,输出 dp[len - 1][0],因为一定有 dp[len - 1][0] > dp[len - 1][1]。

// time:O(n)   space:O(n)
class Solution:
    def maxProfit(self, prices):
		n=len(prices)
        if n<2:return 0
        dp=[[0]*2 for _ in range(n)]
        dp[0][0]=0
        dp[0][1]=-prices[0]
        for i in range(1,n):
            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])
        return dp[n-1][0]
// 改进版,复杂度同上
class Solution:
	def maxProfit(self, prices):
		n=len(prices)
		if n<2:return 0
		//hold:持有股票
		//cash:持有现金
		//状态转移:cash->hold->cash->hold->cash->hold->cash
		cash,hold=0,-princes[0]
		preCash,preHold=cash,hold
		for i in range(n):
			cash=max(preCash,preHold+princes[i])
			hold=max(preHold,preCash-princes[i])
            preCash=cash
            preHold=hold
        return cash