找到我写的这个函数的大 O 来打印 trie 中的所有单词
Finding big O of this function I wrote to print all the words in a trie
我做了这个尝试
class Trie:
def __init__(self):
self.root = {}
self.end = '[=10=]'
def add(self,text):
node = self.root
for letter in text:
if letter in node:
node = node[letter]
else:
node[letter]={}
node = node[letter]
node[self.end] = True
def addAll(self,lst):
for word in lst:
self.add(word)
并制作了这个函数来打印 trie 中的所有单词
# takes in trie.root
def printWords(root,word=""):
if root==True:
print(word[:-1])
return
for letter in root:
printWords(root[letter],word+letter)
如何找到这个函数的大OprintWords
。
最差的时间复杂度是O(²),其中是单词的个数,最长单词的大小。
word+letter
的计算时间复杂度为 O(len(word))。对于在 trie 中出现的给定单词,word+letter
的计算发生 O() 次,每次用一个字符扩展当前前缀,直到找到该单词。这给出了每个单词的时间复杂度 O(²)。
由于树中有单词,在最坏的情况下它们不共享任何前缀,总复杂度为 O(²)
大O应该是上限,换句话说,最坏的情况。
如果树存储 n
个长度为 m_0, m_1, ... , m_(n-1)
的单词,那么在最坏的情况下,它们会沿着树定义 n
个具有上述长度的不相交路径(实际上每条路径都是两个节点长于它所代表的单词,考虑到根节点和结束节点,但这对于大 O 的计算无关紧要)。因此,在最坏的情况下,您会 m_0 + m_1 + ... + m_(n-1)
调用 PrintWords
.
但是,如果树存储了很多单词,上面的估计就过高了,因为一个节点可以拥有的子节点的数量是有限的(最多 27 个 - 每个字母一个 + 结束符号)。因此,如果我们用 h
表示树的高度(其中 h = max(m_0, m_1, ... , m_(n-1))
,那么最多 min(m_0 + m_1 + ... + m_(n-1), 27×h)
调用 PrintWords
。
由于我们正在计算渐近边界,我们可以假设 n
非常大,比 h
大得多,因此最坏的情况变成 27×h
调用,即 O(h)
,其中 h
是最长单词的长度。
您可以更进一步,假设每个词的长度是有界的(自然语言中的词就是这种情况)。假设,你得到渐近界限是 O(1)
。当然,这并不意味着手术很快,可能需要一段时间。但是,由于在最后一个假设下,树的大小是有界的(高度和宽度),因此您对恒定大小(可能非常大)的数据结构执行操作,因此它不会逐渐变得更复杂。你的树变得像一个单词词典 - 即使它包含某种语言的所有单词,它也必须有一个有限的大小,因此可以在有限的时间内完成所有单词。
我做了这个尝试
class Trie:
def __init__(self):
self.root = {}
self.end = '[=10=]'
def add(self,text):
node = self.root
for letter in text:
if letter in node:
node = node[letter]
else:
node[letter]={}
node = node[letter]
node[self.end] = True
def addAll(self,lst):
for word in lst:
self.add(word)
并制作了这个函数来打印 trie 中的所有单词
# takes in trie.root
def printWords(root,word=""):
if root==True:
print(word[:-1])
return
for letter in root:
printWords(root[letter],word+letter)
如何找到这个函数的大OprintWords
。
最差的时间复杂度是O(²),其中是单词的个数,最长单词的大小。
word+letter
的计算时间复杂度为 O(len(word))。对于在 trie 中出现的给定单词,word+letter
的计算发生 O() 次,每次用一个字符扩展当前前缀,直到找到该单词。这给出了每个单词的时间复杂度 O(²)。
由于树中有单词,在最坏的情况下它们不共享任何前缀,总复杂度为 O(²)
大O应该是上限,换句话说,最坏的情况。
如果树存储 n
个长度为 m_0, m_1, ... , m_(n-1)
的单词,那么在最坏的情况下,它们会沿着树定义 n
个具有上述长度的不相交路径(实际上每条路径都是两个节点长于它所代表的单词,考虑到根节点和结束节点,但这对于大 O 的计算无关紧要)。因此,在最坏的情况下,您会 m_0 + m_1 + ... + m_(n-1)
调用 PrintWords
.
但是,如果树存储了很多单词,上面的估计就过高了,因为一个节点可以拥有的子节点的数量是有限的(最多 27 个 - 每个字母一个 + 结束符号)。因此,如果我们用 h
表示树的高度(其中 h = max(m_0, m_1, ... , m_(n-1))
,那么最多 min(m_0 + m_1 + ... + m_(n-1), 27×h)
调用 PrintWords
。
由于我们正在计算渐近边界,我们可以假设 n
非常大,比 h
大得多,因此最坏的情况变成 27×h
调用,即 O(h)
,其中 h
是最长单词的长度。
您可以更进一步,假设每个词的长度是有界的(自然语言中的词就是这种情况)。假设,你得到渐近界限是 O(1)
。当然,这并不意味着手术很快,可能需要一段时间。但是,由于在最后一个假设下,树的大小是有界的(高度和宽度),因此您对恒定大小(可能非常大)的数据结构执行操作,因此它不会逐渐变得更复杂。你的树变得像一个单词词典 - 即使它包含某种语言的所有单词,它也必须有一个有限的大小,因此可以在有限的时间内完成所有单词。