【问题标题】:Function Failing at Large List Sizes函数在大列表大小时失败
【发布时间】:2021-02-20 23:57:17
【问题描述】:

我有一个问题:从 1 索引的零数组和操作列表开始,为每个操作添加一个值到两个给定索引之间的每个数组元素,包括两个给定索引。执行完所有操作后,返回数组中的最大值。

示例:n = 10,查询 = [[1,5,3],[4,8,7],[6,9,1]]

以下将是遍历数组后的结果输出,索引 1-5 将添加 3 等等...:

[0,0,0, 0, 0,0,0,0,0, 0]
[3,3,3, 3, 3,0,0,0,0, 0]
[3,3,3,10,10,7,7,7,0, 0]
[3,3,3,10,10,8,8,8,1, 0]

最后你在最终列表中输出最大值:

[3,3,3,10,10,8,8,8,1, 0]

我目前的解决方案:

def Operations(size, Array):
    ResultArray = [0]*size
    Values = [[i.pop(2)] for i in Array]

    for index, i in enumerate(Array):

        #Current Values in       =  Sum between the current values in the Results Array AND the added operation of equal length
        #Results Array
        ResultArray[i[0]-1:i[1]] = list(map(sum, zip(ResultArray[i[0]-1:i[1]], Values[index]*len(ResultArray[i[0]-1:i[1]]))))

    Result = max(ResultArray)
    return Result

def main():

    nm = input().split()

    n = int(nm[0])

    m = int(nm[1])

    queries = []

    for _ in range(m):
        queries.append(list(map(int, input().rstrip().split())))

    result = Operations(n, queries)
if __name__ == "__main__":
    main()

示例输入:第一行包含两个空格分隔的整数 n 和 m,数组的大小和操作数。 接下来的 m 行中的每一行都包含三个以空格分隔的整数 a、b 和 k,即左索引、右索引和求和。

5 3
1 2 100
2 5 100
3 4 100

大尺寸编译器错误: 运行时错误

目前,此解决方案适用于长度为 4000 的较小最终列表,但是在长度 = 10,000,000 的订单测试用例中,它失败了。我不知道为什么会这样,而且我不能提供示例输入,因为它太大了。有什么清楚的说明为什么它会在更大的情况下失败?

【问题讨论】:

  • 你有堆栈跟踪吗?会不会只是内存问题?
  • 不知道堆栈跟踪是什么。这是 HackerRank 提出的一个问题,称为 Array Manipulation。如果您想检查真实的测试用例。
  • 有错误提示吗?
  • 该站点将显示:编译器错误 - 运行时错误。这就是我能说的全部,因为我自己无法运行大规模的测试示例,我正在处理网站提供的内容。
  • 附带说明,这类问题并不是像您目前所做的那样被蛮力强迫,而是使用一种称为段树的特殊数据结构:link

标签: python python-3.x


【解决方案1】:

我认为问题在于你在这里列出了太多的中间人名单:

ResultArray[i[0]-1:i[1]] = list(map(sum, zip(ResultArray[i[0]-1:i[1]], Values[index]*len(ResultArray[i[0]-1:i[1]]))))

这个ResultArray[i[0]-1:i[1]] 产生一个列表,你做了两次,一次只是为了获得大小,这完全浪费资源,然后你用Values[index]*len(...) 制作另一个列表,最后编译成另一个一旦将其分配到原始列表中,该列表也将被丢弃,因此您制作了 4 个丢弃列表,例如,假设切片大小为 5.000.000,那么您将制作其中的 4 个或额外的 20.000.000您正在消耗的空间,其中 15.000.000 个您并不真正需要,如果您的原始列表包含 10.000.000 个元素,那么只需计算一下...

您可以通过类似列表理解的方式为您的 list(map(...)) 获得相同的结果

[v+Value[index][0] for v in ResultArray[i[0]-1:i[1]] ]

现在我们使用了两个更少的列表,并且我们可以通过使其成为生成器表达式来减少一个列表,因为切片分配不需要您专门分配一个列表,只需一个可迭代的东西

(v+Value[index][0] for v in ResultArray[i[0]-1:i[1]] )

我不知道切片分配是否在内部首先使它成为一个列表,但希望它不会,然后我们回到一个额外的列表

这是一个例子

>>> a=[0]*10
>>> a
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> a[1:5] = (3+v for v in a[1:5])
>>> a
[0, 3, 3, 3, 3, 0, 0, 0, 0, 0]
>>> 

我们可以通过使用 itertools.islice 将它减少到零额外列表(假设在内部它不会生成一个)

>>> import itertools
>>> a[3:7] = (1+v for v in itertools.islice(a,3,7))
>>> a
[0, 3, 3, 4, 4, 1, 1, 0, 0, 0]
>>> 

【讨论】:

    猜你喜欢
    • 2018-12-29
    • 1970-01-01
    • 2019-03-30
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 2016-07-19
    相关资源
    最近更新 更多