Python 代码片段的大O,带“O”;在;列表上的操作

Python 代码片段的大O,带“O”;在;列表上的操作,python,time-complexity,big-o,Python,Time Complexity,Big O,下面这段代码的最大优点是什么 with open(file_name) as f: for word in f: w = word.rstrip() k = ''.join(sorted(w)).lower() if k in words: words[k].append(w) else: words[k] = [w] list中的x是O(n),但此代码未对列表执行成员资格测

下面这段代码的最大优点是什么

with open(file_name) as f:
    for word in f:
        w = word.rstrip()
        k = ''.join(sorted(w)).lower()
        if k in words:
            words[k].append(w)
        else:
            words[k] = [w]

list中的
x
O(n)
,但此代码未对
列表执行成员资格测试<代码>单词看起来像是一个
dict
,在
dict
的键(或
集合中的
中)中的成员资格测试是
O(1)
(从技术上讲,最坏的情况可能是
O(n)
,但这是平均情况
O(1)
,他们甚至努力阻止故意造成碰撞的企图)

使用
集合可以稍微简化此代码。但是defaultdict
,因此在查找不存在的键时,创建
列表
s是隐式完成的:

import collections

words = collections.defaultdict(list)
with open(file_name) as f:
    for word in f:
        w = word.rstrip()
        words[''.join(sorted(w)).lower()].append(w)
如果您想要唯一性(尽管它会失去顺序),只需更改为
defaultdict(set)
,并将
append
更改为
add
。如果您需要唯一性和排序,
collections.OrderedDict
可以(大部分)作为一个有序的
集合使用:

import collections

words = collections.defaultdict(collections.OrderedDict)
with open(file_name) as f:
    for word in f:
        w = word.rstrip()
        # True is placeholder, any value will do if you're using in tests properly
        words[''.join(sorted(w)).lower()][w] = True

words
中的
k将具有线性复杂度,即,如果
words
是一个列表,则O(len(words))

看起来
words
是一个
dict
,但是,由于
words[k]
显然是通过一个字符串对其进行索引,所以列表不会接受这一点


对于
dict
,访问时间可视为常数O(1),用于搜索(
中的
)和更新。(这是摊销时间。)

您的问题是什么?代码中有几个部分对时间复杂度有影响<例如,code>sorted()
@klauds中应该有远不止一个
。我能肯定地说这不是O(N)吗?排序的平均复杂度应该是
O(N logn)
。有关详细信息,请参阅。我认为所有的复杂性都是O(N)+O(N log N),所以它是O(N log N)
单词
由字符串索引,它不能是列表。@JohnDoLittle:
单词
绝对不是
列表
。您正在使用一个
str
在其中执行查找,如果它是一个
列表
,您将得到重复的
类型错误:列表索引必须是整数或片,而不是str
;它是一个
list
s的
dict
,或某种深奥(非内置)类型。由于您从未测试
dict
(即
list
s)的值中的成员资格,因此您从未支付任何
O(n)
查找成本,感谢您解释整个片段?整个片段读取一个文件,因此时间将由I/O控制。如果您没有过长的单词,那么读取的字符数显然是线性的。算法上最慢的部分是调用
sorted
,它是O(n*log(n)),其中n=
len(w)
。如果你所有的单词都比整个文本短得多,那么它可以被认为是一个常数,整个片段就是O(文件长度)。如果您碰巧有一个由2或3个超长单词组成的文本,则性能将由排序的
控制(对数线性),但这是一个边缘情况。让我们分解一下,读取文件中N行的复杂性是O(N),将排序的(w)与N-1进行比较的复杂性是O(N对数N)。因此,在我看来,主要的运算是排序的(w),也就是O(n logn),这取决于我们谈论的n是什么。整个过程是O(k*s),其中k是字符数(我们精确扫描每个字符一次),s是分析每个单词的复杂性(拆分为单词是每个字符O(1))。如果w=len(最长字)