买卖股票的最佳时机系列(go)

1 买卖股票的最佳时机 I (只买卖一次)

问题描述

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

思路:

1 暴力解法:循环遍历两次,记录买入和卖出的差值,取最大值

2 贪心算法;只遍历一次,记录波谷,当到达波峰时,记录差值,最后保留最大值。

3 动态规划:
(1):确定dp
dp[i][0]: 第i天持有股票,此时手里的最大金钱
dp[i][1]: 第i天不持有股票,此时手里的最大金钱

(2):状态变化规则
dp[i][0] = max(dp[i-1][0],-price[i]) // 其实这里要保证买入时股票价格尽可能小,而加了负号,所以去最大值
dp[i][1] = max(dp[i-1][0]+price[i], dp[i-1][1])

(3)初始化
dp[0][0] = -price[0]
dp[0][0] = 0

(4) 顺序:
从前往后

(5)举例子
。。。。

go语言实现
func maxProfit(prices []int) int {
//暴力
    // res := 0
    // for i:=0; i<len(prices)-1;i++ {
    //     for j:=i+1; j<len(prices);j++{
    //         if (prices[j]-prices[i]) >res {
    //             res = prices[j]- prices[i]
    //         }
    //     }
    // }
    // return res
// 贪心
    // m := prices[0] 
    // for i:=1; i<len(prices); i++ {
    //     if prices[i]>m {
    //         if (prices[i]-m)>res {
    //             res = prices[i] -m
    //         }
    //     } else {
    //         m = prices[i]
    //     }
    // }
    // return res
//动态规划
    length := len(prices)
    dp := make([][]int,length)
    for i:=0;i<length;i++ {
        dp[i] = make([]int,2)
    }
    dp[0][0] = -prices[0]
    dp[0][1] = 0
    for i:=1;i<length;i++ {
        dp[i][0] = max(dp[i-1][0],-prices[i])
        dp[i][1] = max(dp[i-1][0]+prices[i], dp[i-1][1])
    }
    return dp[length-1][1]
}
func max(a,b int) int{
    if a>b { return a}
    return b
}

买卖股票的最佳时机II (可以买卖多次)

问题描述

给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格。

在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。
返回 你能获得的 最大 利润 。

思路

和上一个的动态规划思路基本一致:
不同:
买卖一次:
-price[i] :只买卖一次,很好理解。
dp[i][0] = max(dp[i-1][0],-price[i])

卖买多次:
dp[i-1][1] - price[i] : 这个时通过上一次不持有股票的状态传递下来

dp[i][0] = max(dp[i-1][0],dp[i-1][1] - price[i])

go语言实现
func maxProfit(prices []int) int {
    if len(prices) == 1{
        return 0
    }
    length := len(prices)
    dp := make([][]int,length)
    for i:=0;i<length;i++ {
        dp[i] = make([]int,2)
    }
    dp[0][0] = -prices[0] //持有股票
    for i:=1;i<length;i++ {
        dp[i][0] = max(dp[i-1][0],dp[i-1][1]-prices[i])
        dp[i][1] = max(dp[i-1][0]+prices[i], dp[i-1][1])
    }
    return dp[length-1][1]
}
func max(a,b int) int{
    if a>b { return a}
    return b
}

买卖股票的最佳时机系列III (限定交易的次数)

问题描述

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

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)

思路

确定dp:

不管有多少个股票,我们针对一个股票有以下几种状态:
dp[i][0] : 不操作
dp[i][1] : 第一次持有股票 ,手里最大金额
dp[i][2] : 第一次 将持有股票卖出,手里最大金额
dp[i][3] : 第二次持有股票,手里最大金额
dp[i][4] : 第二次将持有股票卖出,手里最大金额
遍历所有股票,更新上述的状态,

状态变化规则:

dp[i][0] = dp[i-1][0] //不变
//1 上一次持有股票 2 上一次不持有股票 - 当前股票的价值,比较1 2大小
dp[i][1] = max( dp[i-1][1], dp[i-1][0] -price[i] )
//1 上一次不持有股票 2 上一次持有股票 + 当前股票的价值,比较1 2大小
dp[i][2] = max( dp[i-1][2] , dp[i-1][1]+price[i] )
//和上面类似
dp[i][3] = max( dp[i-1][3] , dp[i-1][2]- price[i] )
dp[i][4] = max( dp[i-1][4] , dp[i-1][3]+price[i] )

初始化
此时只有一个股票
dp[0][0] =0
dp[0][1] = -price[0]
dp[0][2] =0
dp[0][3] = -price[0]
dp[0][4] =0

遍历的顺序:
从前往后

举例
。。。。

go语言实现
func maxProfit(prices []int) int {

     dp:=make([][]int,len(prices))
    for i:=0;i<len(prices);i++{
        dp[i]=make([]int,5)
    }
    dp[0][0]=0
    dp[0][1]=-prices[0]
    dp[0][2]=0
    dp[0][3]=-prices[0]
    dp[0][4]=0
    for i:=1;i<len(prices);i++{
        dp[i][0]=dp[i-1][0]
        dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
        dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i])
        dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i])
        dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i])
    }
    return dp[len(prices)-1][4]
}
func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

买卖股票的最佳时机IV (限定交易的次数为K)

问题描述

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

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

思路

和上述的思路一样,只是把 2 换成了 K

归纳总结。

go语言实现
func maxProfit(k int, prices []int) int {
    if len(prices)==0 || k==0 {
        return 0
    }

    dp:=make([][]int,len(prices))
    for i:=0;i<len(prices);i++{
        dp[i]=make([]int,2*k+1)
    }
    for i := 0 ; i<2*k+1 ; i++ {
        if i%2==0 {
            dp[0][i] = 0
        } else {
            dp[0][i] = -prices[0]
        }
    }
    for i:=1;i<len(prices);i++{
        dp[i][0] = dp[i-1][0]
        for j :=1;j <2*k+1; j++ {
            if j%2 == 0 {
                dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]+prices[i])
            } else {
                dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]-prices[i])
            }
        }
    }
    //fmt.Println(dp)
    return dp[len(prices)-1][2*k]
}
func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

买卖股票的最佳时机含冷冻期(冷冻期)

问题描述

给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

思路:

状态:
1 持有股票
2 不持有股票,但是度过了冷冻期
3 今天卖出股票,
4 不持有股票,为冷冻期

没遍历一次股票,更新状态:

go语言实现
func maxProfit(prices []int) int {
    length := len(prices)
    res := make([][]int,length)
    for i:=0; i<len(res) ;i++{
        res[i]= make([]int,4)
    }
    res[0][0]= -prices[0]
    for i:=1;i<len(res);i++{
        //持有股票的状态
        //1 昨天也持有股票 2 昨天不持有股,已经度过冷冻 3 昨天是冷冻期,今天就不是了 ,比较 1 2 3 的大小
        res[i][0] = max(res[i-1][0],max(res[i-1][1]-prices[i],res[i-1][3]-prices[i]))
        //已经度过冷冻期,不持有股票
        //等价于:1 昨天度过冷冻期,不持有股,2 昨天为冷冻期 。两者最大值。
        res[i][1] = max(res[i-1][1],res[i-1][3])
        res[i][2] = res[i-1][0] + prices[i] //今天卖出股票 :等价于昨天持有股票,今天卖出

        res[i][3] = res[i-1][2] //今天是冷冻期,所以等价于昨天卖出
    }
    return  max(res[length-1][1],max(res[length-1][2],res[length-1][3]))
}
func max(a,b int) int{
    if a>b { return a}
    return b
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容