简体   繁体   English

如何优化严格递增的基于堆栈的列表

[英]How to optimise a strictly increasing stack based list

So I am trying to solve https://leetcode.com/problems/daily-temperatures Basically given an array [30,40,50,60] we need to return the indices of the next increasing value so output would be [1,1,1,0] My algorithm is to所以我正在尝试解决https://leetcode.com/problems/daily-temperatures基本上给定一个数组 [30,40,50,60] 我们需要返回下一个递增值的索引,因此 output 将是 [1, 1,1,0] 我的算法是

  1. while end !=0 read from the array while end !=0 从数组中读取
  2. if last element add 0 to output and stack如果最后一个元素将 0 添加到 output 并堆栈
  3. Else if temperature[end] > stack top add to stack and add stack top to be the temperature difference.否则,如果 temperature[end] > stack top add to stack 和 add stack top 作为温度差。
  4. If temperature[end] <= stack top then we pop every element until this condition breaks and update the stack top and output.如果 temperature[end] <= stack top,那么我们会弹出每个元素,直到此条件中断并更新 stack top 和 output。

I keep getting a time limit exceeded here, My understanding here is that the complexity is O(N).我一直在这里超出时间限制,我的理解是复杂度是 O(N)。 I am not sure how to optimise it further.我不确定如何进一步优化它。

def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        output = []
        r = len(temperatures) - 1
        stack = []
        while r >= 0:
            if r == len(temperatures) - 1:
                stack.append(r)
                output.insert(0, 0)
            else:
                if temperatures[stack[-1]] > temperatures[r]:
                    output.insert(0, stack[-1]-r)
                    stack.append(r)
                else:
                    while stack and temperatures[stack[-1]] <= temperatures[r]:
                        stack.pop()
                    if len(stack) == 0:
                        output.insert(0, 0)
                        stack.append(r)
                    else:
                        output.insert(0, stack[-1]-r)
                        stack.append((r))

            r -= 1
        return output

An efficient implementation of a slow algorithm will still scale slowly.慢速算法的有效实现仍将缓慢扩展。 Optimizing the stack won't change the big-O.优化堆栈不会改变大 O。 But I'll outline an idea using a different data structure for you to figure out.但我将使用不同的数据结构概述一个想法,供您理解。

In example1 of the problem you start with the array [73,74,75,71,69,72,76,73] .在问题的 example1 中,您从数组[73,74,75,71,69,72,76,73]开始。 Let's arrange this in terms of maxes of ranges like so:让我们根据范围的最大值来安排它,如下所示:

x = [
    [73,74,75,71,69,72,76,73],
    [   74,   75,   72,   76],
    [         75,         76],
    [                     76],
]

In other words x[i][j] gives the max of all elements from j * 2**i to (j+1) * 2**i - 1 .换句话说x[i][j]给出从j * 2**i(j+1) * 2**i - 1的所有元素的最大值。

Now to find the first rise after k we go "forward and down" until we find a block with a larger (or 0 if there is none) and then "up and forward" until we find where it is.现在要找到k之后的第一个上升,我们 go “向前和向下”直到我们找到一个更大的块(如果没有,则为 0)然后“向上和向前”直到我们找到它的位置。 Where:在哪里:

while going forward and down at (i, j): if j is even: if j not at end of x[i]: move to (i, j+1) then test else: answer is 0 else: move to (i+1, j//2 + 1) then test在 (i, j) 处向前和向下时:如果 j 是偶数:如果 j 不在 x[i] 的末尾:移动到 (i, j+1) 然后测试 else:答案为 0 else: 移动到 (i +1, j//2 + 1) 然后测试

while going up and forward at (i, j) with 0 < i: if answer in range for (i-1, j+j): move to (i-1, j+j) else: move to (i-1, j+j+1)在 (i, j) 向上和前进时 0 < i:如果答案在 (i-1, j+j) 的范围内:移动到 (i-1, j+j) 否则:移动到 (i-1 , j+j+1)

For example if k was 2 we would do this.例如,如果k2 ,我们会这样做。

start at (0, 2)
go f&d to (0, 3), check if 75 < x[0][3] (ie 71), stay f&d
go f&d to (1, 2), check if 75 < x[1][2] (ie 72), stay f&d
go f&d to (1, 3), check if 75 < x[1][3] (ie 76), switch to u&f
check if 75 < x[0][6] (ie 76) go u&f to (0, 6)

And now we know that the next one is at position 6. So we get 6 - 2 == 4 there.现在我们知道下一个在 position 6。所以我们得到6 - 2 == 4那里。

What is the performance?表现如何? The whole data structure is O(n) to build.整个数据结构是O(n)来构建的。 Each lookup is at worst O(log(n)) .每个查找最坏的情况是O(log(n)) So doing the n checks is at worst O(n log(n)) .所以做n次检查是最坏的O(n log(n)) Which should be fast enough.这应该足够快。

My Solution is我的解决方案是

def dailyTemperatures(self, temperatures):
    res = []
    i = 0
    while i < len(temperatures) - 1:
        j = i + 1
        while True:
            if j >= len(temperatures):
                res.append(0)
                break
            if temperatures[j] <= temperatures[i]:
                j += 1
            else:
                res.append(j - i)
                break
        i += 1
    res.append(0)
    return res
    

After considerable testing, your answer IS linear.经过大量测试,您的答案是线性的。 (And therefore better than what I suggested before.) However in order to meet their time limit you need to microptimize everything. (因此比我之前建议的要好。)但是,为了满足他们的时间限制,您需要对所有内容进行微优化。 Meaning get rid of every unneeded if , make sure your comparisons are the fastest possible, etc.意思是去掉所有不需要的if ,确保你的比较是最快的,等等。

I would definitely say that leetcode set the time limit too restrictively for the problem and language performance.我肯定会说 leetcode 对问题和语言性能设置的时间限制过于严格。

def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
    if 0 == len(temperatures):
        return []
    output = [0]
    r = len(temperatures) - 1
    stack = [r]
    r -= 1
    while r >= 0:
        while len(stack) and temperatures[stack[-1]] <= temperatures[r]:
            stack.pop()
        if len(stack) == 0:
            output.append(0)
        else:
            output.append(stack[-1]-r)
        stack.append((r))
        r -= 1
    output.reverse()
    return output

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM