超出运行时间限制的最佳买卖股票时间3的问题。

huangapple go评论73阅读模式
英文:

Runtime Exceeded for Best Time to Buy and Sell Stock 3

问题

这是我用于LeetCode问题的代码 - 买卖股票的最佳时机 III,我的Golang代码通过了203/214个测试用例。对于一个大小为10k的特定输入数组,我的时间限制超过了。有什么想法吗?

我的基本算法如下:

  1. 找到价格下降的索引,并忽略它之前的所有元素。例如,如果一个数组是[5,4,3,2,1,2,3,4],在第4个索引之前价格是下降的。
  2. 找到所有局部最小值和局部最大值。因为你只想在局部最小值时买入,局部最大值时卖出。
  3. 如果只有一次盈利交易,即只有一个局部最小值和一个局部最大值,返回该值。
  4. 通过检查在局部最小值时买入,在局部最大值时卖出的所有排列,找到所有盈利交易对。
  5. 返回最高的交易对。

我的代码:

func maxProfit(prices []int) int {
	//trim left
	temp, i := 0, 1
	for ; i < len(prices) && prices[i] <= prices[temp]; i += 1 {
		temp = i
	}
	if i == len(prices) {
		return 0
	}
	i -= 1

	//find all local lows and highs
	localLows := []int{i}
	localHighs := []int{}
	for j := i + 1; j < len(prices)-1; j += 1 {
		if prices[j] >= prices[j+1] {
			for prices[j] == prices[j+1] {
				j += 1
				if j == len(prices)-1 {
					break
				}
			}
			localHighs = append(localHighs, j)
			for ; j < len(prices)-1 && prices[j] >= prices[j+1]; j++ {
				fmt.Print(j, " j")
			}
			fmt.Println()
			localLows = append(localLows, j)
		}
	}
	if prices[len(prices)-1] > prices[len(prices)-2] {
		localHighs = append(localHighs, len(prices)-1)
	}
	fmt.Println(localLows, localHighs)

	//if only one transaction, return that
	if len(localHighs) == 1 {
		return prices[localHighs[0]] - prices[localLows[0]]
	}
	//find all profitable transaction pairs
	maxProfit := 0
	for j := 0; j < len(localHighs); j += 1 {
		for k := j; k < len(localHighs); k += 1 {
            if prices[localHighs[k]]<prices[localLows[j]]{
                        continue
                    }
			transaction1 := int(prices[localHighs[k]] - prices[localLows[j]])
			for l := k + 1; l < len(localHighs); l++ {
				for m := l; m < len(localHighs); m++ {
                    if prices[localHighs[m]]<prices[localLows[l]]{
                        continue
                    }
					transaction2 := int(prices[localHighs[m]] - prices[localLows[l]])
					// fmt.Println(localLows[j], localHighs[k], localLows[l], localHighs[m])
					if (transaction1 + transaction2) > maxProfit {
						maxProfit = transaction1 + transaction2
					}
				}
			}
		}

	}

	return maxProfit
}
英文:

This is my code for leetcode problem - Best Time to Buy and Sell Stock 3
and my Golang code passes 203/214 test cases. My time limit gets exceeded for a particular input array of size 10k. Any ideas?

By basic algorithm goes as follows :-

  1. Find indices till where the price is decreasing and ignore all elements before it. For eg if an array goes like [5,4,3,2,1,2,3,4], here the price is decreasing till the 4th index.
  2. Find all local minimas and local maximas. Because you wouldn't wanna buy unless it's a local minima likewise for selling
  3. If there's only one profitable transaction, i.e. only one local min and one local max, return that.
  4. Find all profitable transaction pairs by checking for all permutations for buying at a local min and selling at a local max.
  5. Return the highest transaction pair

My code :

func maxProfit(prices []int) int {
//trim left
temp, i := 0, 1
for ; i &lt; len(prices) &amp;&amp; prices[i] &lt;= prices[temp]; i += 1 {
temp = i
}
if i == len(prices) {
return 0
}
i -= 1
//find all local lows and highs
localLows := []int{i}
localHighs := []int{}
for j := i + 1; j &lt; len(prices)-1; j += 1 {
if prices[j] &gt;= prices[j+1] {
for prices[j] == prices[j+1] {
j += 1
if j == len(prices)-1 {
break
}
}
localHighs = append(localHighs, j)
for ; j &lt; len(prices)-1 &amp;&amp; prices[j] &gt;= prices[j+1]; j++ {
fmt.Print(j, &quot; j&quot;)
}
fmt.Println()
localLows = append(localLows, j)
}
}
if prices[len(prices)-1] &gt; prices[len(prices)-2] {
localHighs = append(localHighs, len(prices)-1)
}
fmt.Println(localLows, localHighs)
//if only one transaction, return that
if len(localHighs) == 1 {
return prices[localHighs[0]] - prices[localLows[0]]
}
//find all profitable transaction pairs
maxProfit := 0
for j := 0; j &lt; len(localHighs); j += 1 {
for k := j; k &lt; len(localHighs); k += 1 {
if prices[localHighs[k]]&lt;prices[localLows[j]]{
continue
}
transaction1 := int(prices[localHighs[k]] - prices[localLows[j]])
for l := k + 1; l &lt; len(localHighs); l++ {
for m := l; m &lt; len(localHighs); m++ {
if prices[localHighs[m]]&lt;prices[localLows[l]]{
continue
}
transaction2 := int(prices[localHighs[m]] - prices[localLows[l]])
// fmt.Println(localLows[j], localHighs[k], localLows[l], localHighs[m])
if (transaction1 + transaction2) &gt; maxProfit {
maxProfit = transaction1 + transaction2
}
}
}
}
}
return maxProfit
}

答案1

得分: 0

你是否考虑到你的方法虽然不错,但对于Leetcode来说却不够好?我花了很多时间来理解状态机方程是如何工作的,但在经过了很多思考之后,我终于理解了。

这是该方法的工作代码。

func getMin(v1 int, v2 int) int {
    if v1 < v2 {
        return v1
    }
    return v2
}

func getMax(v1 int, v2 int) int {
    if v1 > v2 {
        return v1
    }
    return v2
}

func maxProfit(prices []int) int {    

    var cp1, cp2, mp1, mp2 int

    cp1 = math.MaxInt
    cp2 = math.MaxInt
    mp1 = 0 
    mp2 = 0

    for i:= 0; i < len(prices); i++ {
        cp1 = getMin(cp1, prices[i])
        mp1 = getMax(mp1, prices[i]-cp1)
        cp2 = getMin(cp2, prices[i]-mp1)
        mp2 = getMax(mp2, prices[i]-cp2)
    }

    return mp2
}

cp1是第一次交易的成本价格。
mp1是第一次交易的最大利润。

如果这个问题只要求单次交易的最大利润,那么解决方案就到此为止,实际上这是这个问题的简化版本。

由于我们有机会执行另一次交易,尽管这次交易不会与前一次交易重叠,我们继续定义cp2和mp2。

cp2和mp2基本上与cp1和mp1相同,只是cp2即第二次交易的成本价格可能小于给定日期的price[i]。

为什么会小呢?
这是因为如果我们从第一次交易中获得了一些利润,我们可以用这笔利润抵消或减少第二次的成本价格,这就是为什么我从cp2中减去利润mp1的原因。

cp2 = getMin(cp2, prices[i]-mp1)

想一想,如果你今天在股市上进行某笔交易赚了100美元,然后什么都没做,当你在当天晚些时候(大约上午11点)进行第二笔交易购买价值250美元的东西时,你可以说你以150美元的价格购买了它(因为你早些时候赚了100美元的利润)。这里也是一样的道理。如果你最终以350美元的价格卖出它,那意味着你总共赚了200美元(你可以说350美元-150美元或250美元-150美元+(第一次交易的100美元),两者意思是一样的)

英文:

Did you consider the fact that your approach is good BUT crucially however not good enough for Leetcode ? I had a hard time understanding how the state machine equations work but after spending a lot of time thinking about it, I finally understood it.

This is the working code for that approach.

func getMin(v1 int, v2 int) int {
if v1 &lt; v2 {
return v1
}
return v2
}
func getMax(v1 int, v2 int) int {
if v1 &gt; v2 {
return v1
}
return v2
}
func maxProfit(prices []int) int {    
var cp1, cp2, mp1, mp2 int
cp1 = math.MaxInt
cp2 = math.MaxInt
mp1 = 0 
mp2 = 0
for i:= 0; i &lt; len(prices); i++ {
cp1 = getMin(cp1, prices[i])
mp1 = getMax(mp1, prices[i]-cp1)
cp2 = getMin(cp2, prices[i]-mp1)
mp2 = getMax(mp2, prices[i]-cp2)
}
return mp2
}

cp1 is the cost price for the 1st transaction.
mp1 is the maximum profit for the 1st transaction.

If this problem only asked for the maximum profit from a single transaction, the solution ends right here and in fact that's the easy version of this problem.

Since we have the option to execute another transaction albeit one which doesn't overlap with the previous transaction, we go ahead and define cp2, mp2.

cp2 and mp2 are basically the same as cp1 and mp1 except for the fact that cp2 i.e. cost price 2 or cost price for the 2nd transaction can be potentially less than the price[i] for that given day.

Why exactly is it less ?
This is because if we made some profit from the 1st transaction then we could use that profit to offset or reduce the the 2nd cost price, which is why I'm subtracting the profit mp1 from cp2.

cp2 = getMin(cp2, prices[i]-mp1)

Think about it, if you made a profit of USD 100 from some transaction today in the stock market around 9 AM and did nothing afterwards, when you go in for your 2nd transaction to buy something for say USD 250 later in the day around 11AM, you could say that you bought it for USD 150 (because you made a profit of USD 100 earlier in the day). It's the same thing here. If you wind up selling this for USD 350, that means you've made a total profit of USD 200 ( either you could say USD350-USD150 OR USD250-USD150 + (USD 100 of 1st transaction, both mean the same)

huangapple
  • 本文由 发表于 2022年6月4日 17:13:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/72498515.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定