繁体   English   中英

Python 如何使列表追加/扩展更快?

[英]Python how do i make list appends / extends quicker?

大家好。

试图在 python 上做得更好,并开始做 leetcode 问题。 我目前正在做一个,目标是捕获水。 链接 => https://leetcode.com/problems/trapping-rain-water/

问题是; 它让我花时间过长。 我的代码肯定效率低下。 在谷歌搜索之后,我发现.append 据说非常慢/效率低。 也是。扩展。

找不到任何使我的代码更快的明显方法; 因此我来到这里。

非常感谢任何回应

class Solution:
    def trap(self, height: List[int]) -> int:
        
        max_height = max(height)
        water_blocks = 0
        for element in range(max_height):
            local_map = []
            element = element + 1
            for block in height:
                if block >= element:
                    local_map.extend([1])
                else:
                    local_map.extend([0])

            if local_map.count(1) > 1:
                first_index = local_map.index(1)
                reversed_list = local_map[::-1]
                last_index = len(local_map) - 1 - reversed_list.index(1)
                water_count = last_index - first_index - 1 - (local_map.count(1) - 2)
                water_blocks += water_count
            else:
                continue
        return water_blocks

尽管可以避免许多countindex调用,但两个大的嵌套循环可能仍然是个问题。 对于外循环, max_height可以是大数,内循环遍历整个列表。 您可能需要提出不同的算法。

我没有 leetcode 帐户,所以我无法真正测试我的代码,但这是我的建议:它只遍历height -list 一次,并带有一个小的内部循环来查找下一个匹配的墙。

class Solution:
    def trap(self, h):
        water = 0
        current_height = 0
        for i, n in enumerate(h):
            # found a "bucket", add water
            if n < current_height:
                water += current_height - n
            else: # found a wall. calculate usable height
                current_height = self.n_or_max(h[i+1:], n)
        return water

    def n_or_max(self, h, n):
        local_max = 0
        for i in h:
            if i > local_max:
                local_max = i
                # that's high enough, return n
                if i >= n:
                    return n
        return local_max

这里有一些提示:

  • 不要使用list.count()list.index() (即尝试删除local_map.count(1)local_map.index(1)reversed_list.index(1) )。 第一个将(在内部)循环整个list ,如果list很大,这显然很昂贵。 第二个将遍历列表,直到找到1 目前,您甚至有两次调用local_map.count(1)将始终返回相同的答案,因此至少只需将结果存储在一个变量中。 在您对block的循环中,您自己构造了local_map ,因此您实际上确实知道它包含的内容,之后您不必再搜索它。 只需将一些if s 放入block s 的第一个循环中。
  • 操作local_map[::-1]不仅在整个list上运行,而且还将整个内容复制到一个新list (向后,但这并没有真正导致问题)。 同样,这个新列表不包含新信息,因此您无需执行此操作即可计算water_count的值。
  • 以上是真正的主要问题。 通过消除element = element + 1可以获得进一步的优化。 只需移动范围,如range(1, max_height + 1)
  • 此外,正如评论中所写,更喜欢list.append(x)list.extend([x]) 它不是很大,但后者必须创建一个附加list (长度为 1),将x放入其中,循环遍历list并将 append 其元素(仅x )添加到大list 最后,长度为 1 的列表被丢弃。 相反, list.append(x)只是将x附加到list ,不需要临时的长度为 1 的list

请注意, list.append()并不慢。 这是一个 function 调用,它总是有点慢,但实际的数据操作很快:恒定时间,甚至巧妙地摊销,正如 juanpa.arrivillaga 所写。

这是看待问题的另一种方式。 这会从左到右扫描垃圾箱,在每个点上,我都会跟踪每个级别有多少单位的水被拦住。 当有一堵高墙时,我们会统计它所筑坝的任何单位,并清除它们。 但是,这仍然会在最后一个测试的旁边获得一个“超时”标志,该测试有大约 10,000 个条目。 在我相对较旧的盒子上需要 20 秒。

class Solution():
    def trap(self, height):
        trapped = 0
        accum = [0]*max(height)
        lastwall = -1

        for h in height:
            # Take credit for everything up to our height.
            trapped += sum(accum[0:h])
            accum[0:h] = [0]*h
            for v in range(h,lastwall):
                accum[v] += 1
            lastwall = max(lastwall,h)

        return trapped

print(Solution().trap([0,1,0,2,1,0,1,3,2,1,2,1])) # 6
print(Solution().trap([4,2,0,3,2,5])) # 9

暂无
暂无

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

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