121. 买卖股票的最佳时机Ⅰ(k=1)
题目
- 给定一个数组 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。
法一、贪心
- 通过维护一个变量 minprice 来记录迄今为止的最低买入价格。然后,遍历股价列表,如果当前价格小于最低买入价格,将更新最低买入价格。如果当前价格大于等于最低买入价格,计算当前价格减去最低买入价格的利润,并将其与当前的最大利润进行比较,选择较大值作为最终的最大利润。
class Solution:
def maxProfit(self, prices: List[int]) -> int:
minprice = float('inf')
maxprofit = 0
for price in prices:
minprice = min(minprice, price)
maxprofit = max(maxprofit, price - minprice)
return maxprofit
法二、动态规划
- 状态有两个:第几天,手上是否持有股票;选择是:买或者卖
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
# 初始化动态规划数组
dp = [[0] * 2 for _ in range(n)]
# base case
dp[0][0] = 0 # 第一天不持有股票,利润为0
dp[0][1] = -prices[0] # 第一天持有股票,利润为-buy
# 状态转移
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], -prices[i]) # 持有股票的情况,取前一天也持有股票和前一天不持有股票但今天买入的最大利润
return dp[n-1][0] # 最后一天不持有股票的利润即为最大利润
优化
- 只需要两个变量存储持有和不持有
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
#base case
a=0 #不持有股票
b=-prices[0] #持有股票
# 状态转移
for i in range(1, n):#前面处理了第一天的情况,直接从第二天开始,可以避免下标越界的发生
a = max(a, b + prices[i]) #不持有股票取上一天不持有,和持有的卖出情况的最大值
b = max(b, -prices[i]) #持有股票取上一天持有,和不持有的买入情况的最大值
return a # 最后一天不持有股票的利润即为最大利润