1.动态规划(后面统一称:DP)的经典案例,其他比如有最小路径和,抢劫珠宝之类。具体可以百度相关dp案例。
2.点击题目查看具体要求,并且输入输出[1],本题要求的是买卖只能一次!或者不操作
给定一个数组,它的第 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。
3.解题思路:
①暴力法:时间复杂度o(n²) 空间复杂度o(n)
②DP:主要的动态方程是
时间复杂度o(n) 空间复杂度o(n),可以使用滚动数组降维到o(1)[3],具体查看参考文献。
③先简化问题,我们可以将n个价格转化成前后两天的差价,比如 [7,1,5,3,6,4]-》》》 [-6,4,-2,3,-2],这样我们就能得到一个简单问题,当然也跟dp有关->最大子序列和。可以参考相应代码。
4.解答
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
makeMoney := make([]int, len(prices)-1, len(prices))
//建立利润切片
for i, _ := range makeMoney {
makeMoney[i] = prices[i+1] - prices[i]
}
// fmt.Println(makeMoney)
//dp的最大子串和
curSum, maxSum := 0,0
for _, v := range makeMoney {
curSum = max(curSum+v, v)
maxSum = max(curSum, maxSum)
}
return maxSum
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
[1]https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/
[2]https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-121-best-time-to-buy-and-sell-stock/
[3]https://blog.csdn.net/l1606468155/article/details/97237588