堆栈操作因超时而终止

时间:2018-06-23 13:47:07

标签: python stack timeout

我正在解决一个问题,我要创建一个堆栈,在该堆栈上实现一系列以字符串数组形式给出的operations(3个变体:push x,{{1} },pop)并在每次操作后打印出堆栈顶部(如果堆栈为空,则打印出inc y x)。 EMPTYPush将按预期运行,并且pop将堆栈中底部的inc元素增加y。似乎很简单。

其他约束如下:

  • 1 <= Operations_cnt <= 2 * 10 ^ 5
  • -10 ^ 9 <= x <= 10 ^ 9
  • 1 <= y <= | z |其中z是操作时堆栈的大小
  • pop永远不会在空堆栈上被调用

这是我写的解决方案:

x

我的函数通过了10/14个测试用例,但最后四个是def superStack(operations): # create stack stack = [] add = stack.append # loop through operations for x in range(operations_cnt): start = operations[x].startswith # if push command, append number to stack and print top of stack if start("push"): add(int(operations[x].split()[1])) print(stack[-1]) # elif pop command, remove last number appended and print new top of stack or EMPTY if empty elif start("pop"): stack.pop() if not stack: print("EMPTY") else: print(stack[-1]) # elif inc command, increase bottom numbers accordingly and print top of stack elif start("inc"): params = operations[x].split() n = int(params[1]) m = int(params[2]) for y in range(n): stack[y] += m print(stack[-1]) 。不幸的是,我只获得了前三个测试用例的输入和输出,所以我对到底出了什么问题不知所措。

如何优化此功能以避免超时?

3 个答案:

答案 0 :(得分:1)

将冗余计算移到循环外。这些步骤需要花费一些时间,这些超时会加到用于超时的任何限制中。

例如,没有理由在int(operations[x].split()[1]循环内重新计算for

您只需要split一次,并且只需将每个拆分元素转换为int一次。

答案 1 :(得分:0)

您可能想看看numpy

我在这里实现inc函数:

import time

size=10**8
half=int(size/2)

stack = [1]*size

start_time = time.time()
for y in range(0,half):
    stack[y] += 2
print("--- %s seconds ---" % (time.time() - start_time))


import numpy as np
stack = np.asarray([1]*size)

start_time = time.time()
stack[0:half] += 2
print("--- %s seconds ---" % (time.time() - start_time))

这个,把这个输出游戏给我:

$ python3 myprog.py
--- 5.146971225738525 seconds ---
--- 0.49752235412597656 seconds ---

请注意,我绝不是numpy的专家,经验丰富的用户可能会有更好的书写方式。我的主要观点是,对于长列表和矩阵的操作,numpy比本地python快得多。

(从https://stackoverflow.com/a/1557584/6699433复制的时间度量)

这是一个完整的类,您基本上只需很少的工作就可以将其插入代码中:

import numpy as np

class Stack:
    def __init__(self):
        self.stack = np.arange(0)

    def pop(self):
        self.stack.resize(len(self.stack)-1)

    def push(self, x):
        self.stack.resize(len(self.stack)+1)
        self.stack[-1]=x

    def inc(self, y, x):
        self.stack[0:y] += x

    def printTop(self):
        if(len(self.stack) == 0):
            print("EMPTY")
        else:
            print(self.stack[-1])

它看起来像这样:

def superStack(operations):
    stack = Stack()
    for x in range(0,operations_cnt):    
        if operations[x].startswith("push"):
            stack.push(int(operations[x].split()[1]))
        elif operations[x].startswith("pop"):
            stack.pop()
        elif operations[x].startswith("inc"):
            stack.inc(int(operations[x].split()[1]), int(operations[x].split()[2]))
        stack.printTop()

答案 2 :(得分:0)

可能会加快处理速度的一件事是利用以下事实:操作数量少于200000。由于扩展堆栈的唯一操作是推入,并且始终仅添加一个元素,因此堆栈永远不需要更大比这个值。请注意,这个想法也可以与我涉及numpy的答案一起使用。

我还更改了inc以利用列表理解。有点快。

class Stack:
    def __init__(self):
        self.stack = [0]*200000
        self.size = 0

    def push(self, x):
        self.stack[self.size]=x
        self.size+=1

    def pop(self):
        self.size-=1

    def inc(self, y, x):
        self.stack[0:y] = [e+x for e in self.stack[0:y]]

    def printTop(self):
        if(self.size == 0):
            print("EMPTY")
        else:
            print(self.stack[self.size-1])