买卖股票的最佳时机
思路一:暴力算法
分别列出第 1 2,,,n 天买入时获取的最大利润,取最大值
思路二:递推
第 i 天买入时的最大价值,与第 i+1 天买入时的最大价值找关系
或 买卖 prices 与买卖 prices[1:] 的关系
错误解法:
买卖 prices 与买卖 prices[1:] 的关系,不好确定,因为无法确定prices[1:] 中的买入时期
func maxProfit(prices []int) int {
//边界条件
if len(prices) < 2 {
return 0
}
if len(prices) == 2 {
if val := prices[1] - prices[0]; val >= 0 {
return val
}
return 0
}
var maxVal int
//不能取后面的最小值,也不能与price[1]比较,因为最小值未必是买入的时机,忽略了买卖顺序!!!
//应该取买入时机的值,但是怎么取买入时机不清楚,所以是错误的
minVal := min(prices[1:])
if prices[0] >= minVal {
maxVal = maxProfit(prices[1:])
} else {
//这个递推公式错误
maxVal = maxProfit(prices[1:]) + minVal - prices[0]
}
return maxVal
}
func min(prices []int) int {
//取切片中的最小值
val := prices[0]
for _, item := range prices {
if item < val {
val = item
}
}
return val
}
错误解法:
以买入日期为返回值的函数,进行递推,也不行,因为递推后的切片变了,买入日期并非原来的买入日期
func maxProfit(prices []int) int {
buyDayI := buyDay(prices)
if buyDayI == -1 {
return 0
}
buyDayVal := prices[buyDayI]
maxDayVal := max(prices[buyDayI+1:])
return maxDayVal - buyDayVal
}
//获取买入时期的函数
func buyDay(prices []int) int {
if len(prices) < 2 {
return -1
}
if len(prices) == 2 {
if val := prices[1] - prices[0]; val >= 0 {
return 0
}
return -1
}
maxVal := max(prices[1:])
buyDayI := buyDay(prices[1:])
if buyDayI == -1 {
//判断最高值与当前值的关系
if prices[0] < maxVal {
//这个return的下标是切片后的0,但是不代表是原来的下标!
return 0
}
} else {
//判断当前值与买入日期值的关系
if prices[0] < prices[buyDayI] {
return 0
}
}
return buyDayI
}
func max(prices []int) int {
//取切片中的最小值
val := prices[0]
for _, item := range prices {
if item > val {
val = item
}
}
return val
}
以买入值、卖出值为返回值的递推函数
仍然有问题。。。原因待研究
func maxProfit(prices []int) int {
buyValI := buyVal(prices)
//知道买入值后,不好知道卖出值
buyIndex := -1
maxVal:=buyValI
for index, item := range prices {
if item == buyValI {
buyIndex = index
}
//找到后面的最大值,返回差值
if buyIndex!=-1 && item>maxVal{
maxVal=item
}
}
return maxVal-buyValI
}
//获取买入值的函数 需要返回两个,不然不好知道卖出值
func buyVal(prices []int) int {
if len(prices) == 1 {
return -1
}
if len(prices) == 2 {
if val := prices[1] - prices[0]; val >= 0 {
return prices[0]
}
return -1
}
maxVal := max(prices[1:])
buyValI := buyVal(prices[1:])
if buyValI == -1 {
//判断最高值与当前值的关系
if prices[0] < maxVal {
//这个return的下标是切片后的0,但是不代表是原来的下标!
return prices[0]
}
} else {
//判断当前值与买入日期值的关系
if prices[0] < buyValI {
return prices[0]
}
}
return buyValI
}
func max(prices []int) int {
//取切片中的最小值
val := prices[0]
for _, item := range prices {
if item > val {
val = item
}
}
return val
}
正确解法:能一次遍历解决,不要先考虑递推
func maxProfit(prices []int) int {
if len(prices)<2{
return 0
}
minPrice:=prices[0]
maxProfits:=0
for _,item:=range prices{
if item<minPrice{
minPrice=item
}
if profit:=item-minPrice;profit>maxProfits{
maxProfits=profit
}
}
return maxProfits
}