繁体   English   中英

如何优化我的 Python 代码以更快地运行?

[英]How can I optimize my Python code to run faster?

如果在其右侧的每个元素(不仅仅是紧邻其右侧的一个元素)都严格小于该元素,则将项目列表的元素定义为支配者。 请注意,根据这个定义,列表的最后一项自动成为支配者。 这个 function 应该计算项目中有多少元素是支配者,并返回该计数。 例如,列表[42, 7, 12, 9, 13, 5]的支配者将是元素42135 列表的最后一个元素是微不足道的支配者,不管它的值如何,因为它后面没有更大的元素。

1

我正在解决这个练习问题并且有一个有效的代码,但是它很慢。 我怎样才能最好地优化它以更快地运行?

def count_dominators(items):
    item_count = len(items)
    count = 0
    if item_count==0:
        return count;
        
    count+=1;
    
    if item_count==1:
        return count;
    
    for i in range(0,len(items)-1):
        flag=1
        for j in range(i+1,len(items)):
            
            if(items[j]>=items[i]):
                flag=0;
                break;
          
       
        if(flag==1):
            count+=1;
    return count
import numpy as np

seq=[42, 7, 12, 9, 13, 5]
dominators=np.unique(np.maximum.accumulate(seq[::-1]))
print(dominators)
>>>[ 5 13 42]

以相反的顺序迭代会将其从O(n²)减少到O(n) ,因为您将在 go 中保持运行最大值,而无需重新扫描每个新元素的所有尾随元素。 因此,无需依赖您未编写的复杂实用程序,您只需执行以下操作:

def count_dominators(items):
    max_so_far = float('-inf')  # Smaller than any value to it's replaced immediately,
                                # identifying first element as dominator by definition

    count = 0
    for item in reversed(items):  # Iterate in reverse order so we only need to know max
                                  # so far to identify new dominators
        if item > max_so_far:
            max_so_far = item
            count += 1
    return count

如果你想要更多的魔法来减少自己的工作,Python 的itertools模块提供了一个accumulate function ,它可以在元素上重复执行操作,产生迄今为止的结果。 如果你使用max作为操作,那么它会生成一个 stream 数字,只有当你看到一个新的支配者时才会改变。 将结果转换为一个set或使用itertools.groupby (在没有 arguments 的情况下运行时大致相当于uniq命令行实用程序,使其成为对相邻重复项进行重复数据删除的廉价方法)进行重复数据删除,以及该set的长度或数量groups 是支配者计数:

from itertools import accumulate, groupby

def count_dominators(items):
    return sum(1 for _, _ in groupby(accumulate(reversed(items), max)))

或者以技术上不必要的为代价,为每个新的支配者set增长(可能更快,因为itertools.groupby的开销比您预期的要多,并且重复数据删除后收集的元素数量可能小到无关紧要):

from itertools import accumulate

def count_dominators(items):
    return len(set(accumulate(reversed(items), max)))

如果您愿意,您可以将sum(1 for _, _ in (以及匹配的尾括号)替换为更有效的方法来计算迭代器中的元素(尽管除非输入很大,否则几乎无关紧要)。

假设只有正数,您可以从列表的末尾开始运行并标记您遇到的最大数字。 这将是 O(n) 复杂性,而不是您建议的 O(n^2)。 像这样的东西会起作用:

def count_dominators(items):
    count = 0
    last_biggest = -1
    for i in range(len(items)-1,-1,-1):
      if items[i] > last_biggest:
        last_biggest = items[i]
        count += 1

    return count

暂无
暂无

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

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