8、买卖股票的最佳时机 II

本文共913字。
展开

题目描述

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

在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。
返回 你能获得的 最大 利润 。

示例 1:

输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii

方法1、贪心算法

思路:

判断后一天价格是否高于前一天,高,就卖。(有钱就卖,即大于0就卖。)

时间复杂度:O(n)

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

1
2
3
4
5
6
7
8
9
class Solution:
def maxProfit(self, prices: List[int]) -> int:
# 收集所有上升时间段买卖(当然这是上帝视角了)
l = len(prices)
r = 0
for i in range(1, l):
if prices[i] > prices[i-1]:
r += prices[i]-prices[i-1]
return r

方法2、动态规划

动态规划就是把大问题拆分成小问题,把几天的问题,拆分成一天一天的买和卖。

思路:

手里的股票分为,有股票和无股票。

时间分为数组长度l的天数。

新建一个二维数组,行=天数,列=有股票和无股票(两列)。

首先第一天,无股票收益 = 0;有股票收益 = -买入股票价格的支出。

之后的天数里:

​ 1、今天无股票的最大利润=max{昨天就无股票(利润保持不变),昨天有股票+今天卖掉的收益}

​ 2、今天有股票的最大利润=max{昨天就有股票(利润保持不变),昨天无股票-今天买进的支出}

最后返回最后一天无股票时候的价格。(有股票的收益一定小于无股票,如果最后一天还有股票,那么最后一天需要支出买入股票的价格,或者持有不动。)

时间复杂度:O(n),n为数组长度。一共有2n个状态。每次状态转移的时间复杂度是O(1),因此总的时间复杂度是O(2n)=O(n)

空间复杂度:O(n)。需要2n个空间存储所有状态,或者看代码二进行空间优化,只需要存昨天的两个值,复杂度降为O(1)。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def maxProfit(self, prices: List[int]) -> int:
# 动态规划
if not prices:
return 0
l = len(prices)
dp = [[0 for x in range(2)] for y in range(l)]
dp[0][0] = 0 # 第一天无股票时的收益
dp[0][1] = -prices[0] # 第一天有股票时的收益
for i in range(1, l):
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[l-1][0] # 返回最后一天无股票的时候的收益

因为当前时刻的收益,只和昨天的有无股票有关,所以只需要存储昨天的值即可。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def maxProfit(self, prices: List[int]) -> int:
# 动态规划, 只存储上一时刻的有无股票值
if not prices:
return 0
l = len(prices)
dp0 = 0
dp1 = -prices[0]
for i in range(1, l):
dp0 = max(dp0, dp1+prices[i])
dp1 = max(dp1, dp0-prices[i])
return dp0