121. 买卖股票的最佳时机-E

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 &gt; = 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 &lt; t &lt; = j } } 1 &lt; i &lt; j &lt; s dp[i][j]=\left\{ \begin{aligned} &amp;0 &amp; i&gt;=j \\ &amp;max\{0,nums[j]-nums[0]\} &amp;i=0\\ &amp;max\{dp[i-1][j],max\{nums[t]-nums[i],i&lt;t&lt;=j\}\} &amp;1&lt;i&lt;j&lt;s \end{aligned} \right. dp[i][j]=0max{0,nums[j]nums[0]}max{dp[i1][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}))
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值