leetcode最大收益I II III

  leetcode最大收益问题接连做了3道,难度逐渐提升,而且第三道直接没有思路,现在做完之后,需要做一个总结。

第一题

https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
在这里插入图片描述
给定一个数组,每一个数代表股票每天的价格,允许你进行一次交易,然后返回可以获得的最大收益。

第一种思路

这个题第一印象就是双重循环,暴力求解,😄,这得益于我的朋友暴力解法的鼻祖。代码如下:

func maxProfit1(prices []int) int {
	res := 0
	for i := 0; i < len(prices) - 1; i++ {
		for j := i + 1; j < len(prices); j++ {
			if prices[i] < prices[j] {
				res = Max(res, prices[j] - prices[i])
			}
		}
	}
	return res
}

上面这一段代码的思路很简单,计算以i为买入,i+1~len(prices)-1中任意一天卖出的最大收益。

第二种思路

/*
一次遍历 累加求和
*/
func maxProfit2(prices []int) int {
	res := 0
	curMax := 0
	for i := 1; i < len(prices); i++ {
		curMax = Max(0, curMax + prices[i] - prices[i-1])
		res = Max(curMax, res)
	}
	return res
}

这个思路也比较好理解,res,curMax分别代表最终结果和当前的最大收益,这个curMax是一个累加的收益。当prices=[1, 2, 3, 4]则curMax开始是1,然后是2,…最后是3。即curMax=(4-3) + (3-2) + (2 - 1)=3。
代码中curMax = Max(0, curMax + prices[i] - prices[i-1])这一句就是在更新curMax,为什么是和0比较大小的,可以看这个例子。当prices=[2, 3, 1, 5],则curMax=[0, 1, 0, 4],在第二个0的位置,若不是和0比较大小,则变成了-1,当卖出的价格1小于买入的价格2时,我们可以选择不在2这个时候买入,若在累加的过程中没有和0比较,则默认我们第一天就买入了,这不符合题意。

第三种思路

记录当前的最小值作为买入的时候,然后在最小值后面的任意时刻卖出获得最大收益。

/*
一次遍历,记录最小值,计算当前值与最小值之间的差值,然后更新较大的差值
*/
func maxProfit3(prices []int) int {
	res, buy := 0, 1<<32
	for _, price := range prices {
		buy = Min(buy, price)
		res = Max(res, price - buy)
	}
	return res
}

第二题

可以进行多次买入卖出交易,计算最大利润
https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/
在这里插入图片描述
既然可以买入卖出多次,那就贪心的去做,只要今天的价格比明天的价格低,就可以今天买,明天卖。

/*
买股票,股票可以买入卖出多次,计算可以获得的最大利润
可以贪心的去操作,只要今天价格比明天低,就可以今天买入,明天卖出,若后天价格更高,则可以明天买入,后天再卖出
*/
func maxProfit(prices []int) int {
	res := 0

	for i := 0; i <= len(prices) - 2; i++ {
		if prices[i] < prices[i+1] {
			res += prices[i+1] - prices[i]
		}
	}
	return res
}

第三题

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/
在这里插入图片描述
这一天为hard,前两题是easy的。这一题没有思路,但是看了别人的代码之后也是发觉不算难。

/*
最大利润,至多进行两次交易,返回可以获得的最大利润
因为是最多两次交易,我们可以执行两次,即分别计算每次交易能获得的最大利润
第一次是先从左到右执行,即遍历一次数组,若当前price小于min,则更新min,这个min用于对后面的数值计算最大收益,
                                  若不小于min,则计算当前price卖出,min买入的收益,
同时用一个left数组存储以i结尾进行一次交易的收益

第二次我们倒着遍历数组,max为当前股票的最大价格,若当前价格大于max,则更新max,max用于对前面的数值计算最大收益
                                         若当前价格price小于max,则说明可以以当前价格price买入,max卖出,获得收益
同时用一个right数组存储以i为开始买入进行一次交易的收益
两次交易有没有冲突?不会的
以   {1, 6, 2, 2, 5, 10, 0}为例,
left=[0, 5, 5, 5, 5, 9, 9]
righ=[9, 8, 8, 8, 5, 0, 0]
分开来看,第一次交易取得最大值是9,而此时right是0
        第二次交易取得最大值是9,而此时left是0
而第一次交易取得5,第二次交易取得8时才是两次交易总和最大的时候
reference:
https://www.youtube.com/watch?v=LX8i5PxRVCg
*/
func maxProfit123(prices []int) int {
	res := 0
	left := make([]int, len(prices))
	right := make([]int, len(prices))
	min := 1<<32
	localMax := 0
	for i := 0; i < len(prices); i++ {
		if prices[i] < min {
			min = prices[i]
		} else {
			if localMax < prices[i] - min {
				localMax = prices[i] - min
			}
		}
		left[i] = localMax
	}
	max := -1000
	localMax = 0
	for i := len(prices) - 1; i >= 0; i-- {
		if prices[i] > max {
			max = prices[i]
		} else {
			if localMax < max - prices[i] {
				localMax = max - prices[i]
			}
		}
		right[i] = localMax
	}
	for i := 0; i < len(prices); i++ {
		if res < left[i] + right[i] {
			res = left[i] + right[i]
		}
	}
	return res
}

func main() {
	prices := []int{1, 6, 2, 2, 10, 0}
	fmt.Println(maxProfit123(prices))
}

但是这题的动态规划做法还没有看懂,后面把动态规划的思路滤清了再补上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值