121. 买卖股票的最佳时机
给定一个数组,它的第 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。
-
分析
本题目求最值,可以考虑一下动态规划;由于是计算差值的最大,所以有买入、卖出两各维度, 1. 卖出时的比较(横向):dp[i][j]表示i时买入,j时卖出的最大价值A=max{dp[k]-dp[i],i<k<=j}, 2. 买入时的比较(纵向):B=max{dp[k][j],0<=0<=i} 3. dp[i][j]=max{A,B} 4. dp计算完整张表,即可得到最大卖出利润计算完整张表,即可得到最大卖出利润为dp[size-1][size-1] 这里,纵向比较,可以直接将结果修改,即可采用以为动态数组dp 递推式子
d p [ i ] [ j ] = { 0 i > = j m a x { 0 , n u m s [ j ] − n u m s [ 0 ] } i = 0 m a x { d p [ i − 1 ] [ j ] , m a x { n u m s [ t ] − n u m s [ i ] , i < t < = j } } 1 < i < j < s dp[i][j]=\left\{ \begin{aligned} &0 & i>=j \\ &max\{0,nums[j]-nums[0]\} &i=0\\ &max\{dp[i-1][j],max\{nums[t]-nums[i],i<t<=j\}\} &1<i<j<s \end{aligned} \right. dp[i][j]=⎩⎪⎨⎪⎧0max{0,nums[j]−nums[0]}max{dp[i−1][j],max{nums[t]−nums[i],i<t<=j}}i>=ji=01<i<j<s
- code
package main
import "fmt"
func maxProfit(prices []int) int {
s:=len(prices)
if s<2{
return 0
}
//动态数组dp
dp:=make([]int,s)
for i:=0;i<s;i++{//买入
for j:=i+1;j<s;j++{//卖出
p:=prices[j]-prices[i]
if p>dp[j] {
dp[j] = p
}
if dp[j-1]>dp[j]{
dp[j]=dp[j-1]
}
}
}
return dp[s-1]
}
func main(){
fmt.Println(maxProfit([]int{7,6,4,3,1}))
}
-
峰值图法 解答:一次遍历
从这个解法看到,动态规划只是一种解法,一种基础方法; 在解决后,别忘了用其他角度看看,可不可以优化 记录峰谷minPrice和maxProfit,通过maxProfit={next-minPrice,maxPrice} 更新最大收益; 这应该也算一种动态规划方法,只是出发方向不一样
-
code
package main
import "fmt"
func maxProfit(prices []int) int {
if len(prices)==0{
return 0
}
minPrice:=prices[0]
maxProfit:=0
for i:=1;i<len(prices);i++{
if prices[i]-minPrice>maxProfit{
maxProfit=prices[i]-minPrice
}
if prices[i]<minPrice{
minPrice=prices[i]
}
}
return maxProfit
}
func main(){
fmt.Println(maxProfit([]int{7,1,5,3,6,4}))
}