买卖股票的最佳时机 I

16 阅读3分钟

买卖股票的最佳时机

思路一:暴力算法

分别列出第 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
}