1.买卖股票的最佳时机
1.1 贪心方法
func maxProfit(prices []int) int {
// 低买高卖
minGetPrice := prices[0]
maxSaleProfit := 0
for i:=0;i<len(prices);i++{
// 检查是否低于最低买入价
if prices[i]<minGetPrice{
minGetPrice = prices[i]
// 尝试在这里卖出
}else if maxSaleProfit<prices[i]-minGetPrice{
maxSaleProfit = prices[i]-minGetPrice
}
}
return maxSaleProfit
}
1.2 动态规划的方法
func maxProfit(prices []int) int {
length := len(prices)
if length == 0 {
return 0
}
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]用来表示第i天之前能买入的最低价,使用负数代表买股票后的负债,负债越小越好,所以这里选择最大值
dp[i][0] = max(dp[i-1][0], -prices[i])
//dp[i][1]用来表示在第前i天卖出能得到的最高理论
dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i])
}
return dp[length-1][1]
}
2.买卖股票的最佳时机II
不同点在于:你可以多次买入卖出股票,但是买入一定在卖出之前。买入之后不可以再买入股票,必须先卖出。
这里用一个[2]int来存储两个不同的情况,[i][0]用来表示第i日持有股票的情况下最大的利润,[i][0]表示第i日不持有股票的情况下的最大利润。
func maxProfit(prices []int) int {
dp := make([][]int,len(prices))
for i:=0; i<len(prices); i++{
dp[i] = make([]int,2)
}
dp[0][0] = -prices[0]
dp[0][1] = 0
for i:=1;i<len(prices);i++{
dp[i][0] = max(dp[i-1][0],dp[i-1][1]-prices[i])
dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i])
}
return dp[len(prices)-1][1]
}
3.买卖股票的最佳时机III
思路:这里我们给每个dp设置了5个状态。每个状态都依赖于前一个状态进行推导。
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][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])
}
maxProfit := 0
for i:=1;i<5;i++{
if dp[len(prices)-1][i]>maxProfit{
maxProfit = dp[len(prices)-1][i]
}
}
return maxProfit
}
4.买卖股票的最佳时机IV
没什么好说的,直接看代码
func maxProfit(k int, prices []int) int {
dp := make([][]int,len(prices))
/**
没有操作
第一次持有股票
第一次不持有股票
.....
第k次持有股票
第k次不持有股票
**/
for i:=0; i<len(prices); i++{
dp[i] = make([]int,2*k+1)
}
// 初始化
for i:=0;i<k;i++{
dp[0][i*2+1] = -prices[0]
}
// 开始递推公式
for i:=1;i<len(prices);i++{
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])
}
}
}
maxProfit := 0
for i:=1;i<2*k+1;i++{
if dp[len(prices)-1][i]>maxProfit{
maxProfit = dp[len(prices)-1][i]
}
}
return maxProfit
}
5.最佳买卖股票时机含冷冻期
func maxProfit(prices []int) int {
dp := make([][]int, len(prices))
/**
状态总数n
状态0:持有股票状态
状态1:不持有股票,且不在冷冻区
状态2:今天卖出股票
状态3:今天为冷冻区
**/
n := 4
for i := 0; i < len(prices); i++ {
dp[i] = make([]int, n)
}
// 初始化
dp[0][0] = -prices[0]
dp[0][1] = 0
dp[0][2] = 0
dp[0][3] = 0
//fmt.Println(dp)
//递推公式
for i := 1; i < len(prices); i++ {
//今天买股票,则前一天为状态0、1、3
dp[i][0] = max(dp[i-1][0], max(dp[i-1][3], dp[i-1][1])-prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][3])
dp[i][2] = dp[i][0] + prices[i]
dp[i][3] = dp[i-1][2]
//fmt.Println(dp)
}
//返回结果
profit := 0
for i := 0; i < n; i++ {
if profit < dp[len(prices)-1][i] {
profit = dp[len(prices)-1][i]
}
}
return profit
}
6.买卖股票的最佳时机含手续费
func maxProfit(prices []int, fee int) int {
dp := make([][]int,len(prices))
/**
状态数n=2
0:持有股票
1:不持有股票
**/
n := 2
for i:=0;i<len(prices);i++{
dp[i]=make([]int,n)
}
//初始化
dp[0][0] = -prices[0]
dp[0][1] = 0
//递推函数
for i:=1;i<len(prices);i++{
dp[i][0] = max(dp[i-1][0],dp[i-1][1]-prices[i])
dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i]-fee)
}
//返回结果
return max(dp[len(prices)-1][0],dp[len(prices)-1][1])
}