买卖股票的最佳时机


题目来源:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock

题目


给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。

示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

解题思路


将求差问题转换为区间和的问题。

这里采用牛顿莱布尼兹公式来侧面说明下转换的问题:

牛顿莱布尼兹公式

但是在这里 F() 并不是连续的,而是离散的,a 和 b 代表的是数组的下标。

在这里 F() 表示的数组称为前缀和。

前缀和:一个数组的某项下标之前(包括此项元素)的所有数组元素的和

这样,求差问题就可以转换为区间和的问题。

最大连续子数组和的问题,可以使用动态规划来求解。

dp[i] 表示以 i 结尾的最大连续子数组和,结合题意,状态转移方程为:dp[i]=max(0, dp[i-1]+diff[i])

这里 dp[i] 数组可被优化,所以上面的式子可变为:

last = max(0, last + diff[i])

其中 diff[i] = prices[i + 1] - prices[i],表示相隔两天股票价格的差值。所以上面的式子可进一步优化为:

last = max(0, last + prices[i + 1] - prices[i])

代码实现


class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        last, profit = 0, 0
        for i in range(len(prices) - 1):
            last = max(0, last + prices[i+1] -prices[i])
            profit = max(profit, last)

        return profit

实现结果


实现结果

参考


引用

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/121-mai-mai-gu-piao-de-zui-jia-shi-ji-dp-7-xing-ji/


以上就是使用数学方法,将求差转换为求区间和,解决《买卖股票的最佳时机》问题的主要内容。

欢迎关注微信公众号《书所集录》
欢迎关注微信公众号《书所集录》

大梦三千秋
41 声望5 粉丝

为而不争