我设计了一个递归算法并用 Python 写下来。当我用不同的参数测量运行时间时,似乎需要指数级的时间。此外; 以 50 之类的小数字结束需要半个多小时。(我没有等到它完成,但它似乎没有在合理的时间内完成,猜测它是指数的)。
所以,我很好奇这个算法的运行时间复杂度。有人可以帮我推导出方程 T(n,m) 吗?或者计算大哦?
算法如下:
# parameters:
# search string, the index where we left on the search string, source string, index where we left on the source string,
# and the indexes array, which keeps track of the indexes found for the characters
def find(search, searchIndex, source, sourceIndex, indexes):
found = None
if searchIndex < len(search): # if we haven't reached the end of the search string yet
found = False
while sourceIndex < len(source): # loop thru the source, from where we left off
if search[searchIndex] == source[sourceIndex]: # if there is a character match
# recursively look for the next character of search string
# to see if it can be found in the remaining part of the source string
if find(search, searchIndex + 1, source, sourceIndex + 1, indexes):
# we have found it
found = True # set found = true
# if an index for the character in search string has never been found before.
# i.e if this is the first time we are finding a place for that current character
if indexes[searchIndex] is None:
indexes[searchIndex] = sourceIndex # set the index where a match is found
# otherwise, if an index has been set before but it's different from what
# we are trying to set right now. so that character can be at multiple places.
elif indexes[searchIndex] != sourceIndex:
indexes[searchIndex] = -1 # then set it to -1.
# increment sourceIndex at each iteration so as to look for the remaining part of the source string.
sourceIndex = sourceIndex + 1
return found if found is not None else True
def theCards(N, colors):
# allcards: a list 1..N of characters where allcards[i] is 'R' if i is a prime number, 'B' otherwise.
# so in this example where N=7, allcards=['B','R','R','B','R','B','R']
allcards = ['R' if isPrime(i) else 'B' for i in range(1, N + 1)]
# indexes is initially None.
indexes = [None] * len(colors)
find(colors, 0, allcards, 0, indexes)
return indexes
if __name__ == "__main__":
print theCards(7, list("BBB"))
我不知道是否必须了解问题和算法才能得出最坏情况的运行时间,但这是我试图解决的问题:
问题:
给定一个源字符串 SRC 和一个搜索字符串 SEA,在 SRC 中找到子序列 SEA,并返回在 SRC 中找到 SEA 的每个字符的索引。如果 SEA 中的一个字符可以在 SRC 中的多个位置,则为该字符位置返回 -1。
例如; 如果源字符串是 BRRBRBR (N=7) 并且搜索字符串是 BBB:那么 'BBB' 中的第一个 'B' 可以出现在搜索字符串的索引 0 处。第二个“B”可以位于搜索字符串的索引 3,最后一个“B”可以位于第 5 个位置。此外; 字符“BBB”的位置没有其他替代方案,因此算法返回 [0,3,5]。
在另一种情况下,源字符串是 BRRBRB (N=6) 并且搜索字符串是 RBR:“RBR”的第一个“R”可以位于位置 1 或 2。这仅留下位置 3 用于“B”和位置最后一个“R”为 4。然后,第一个“R”可以在多个位置,它的位置是模棱两可的。其他两个字符 B 和 R 只有一个位置。所以算法返回 [-1,4,5]。
] (N=58),搜索字符串为 RBRRBRBBRBRRBBRRBBBRRBBBRR。它应该返回 [-1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 23, -1, -1, -1, -1, -1 , -1, -1, -1, -1, -1, -1, -1, 47, 53 ],但不幸的是它没有 =(
优化:
当“索引”列表完全充满 -1 时,我想停止搜索。但这只会影响最好的情况(或者可能是平均情况),而不是最坏的情况。如何进一步优化该算法。我知道这个问题存在多项式解决方案。
比优化更重要的是,我真的很好奇运行时间的 T(n,m) 方程,其中 n 和 m 是源字符串和搜索字符串的长度。
如果你能读到这里,非常感谢你!=)
编辑 - IVIad 的解决方案已实施:
def find2(search, source):
indexes = list()
last = 0
for ch in search:
if last >= len(source):
break
while last < len(source) and source[last] != ch:
last = last + 1
indexes.append(last)
last = last + 1
return indexes
def theCards(N, colors):
# allcards: a list 1..N of characters where allcards[i] is 'R' if i is a prime number, 'B' otherwise.
allcards = ['R' if isPrime(i) else 'B' for i in range(1, N + 1)]
indexes = find2(colors, allcards) # find the indexes of the first occurrences of the characters
colors.reverse() # now reverse both strings
allcards.reverse()
# and find the indexes of the first occurrences of the characters, again, but in reversed order
indexesreversed = find2(colors, allcards)
indexesreversed.reverse() # reverse back the resulting list of indexes
indexesreversed = [len(allcards) - i - 1 for i in indexesreversed] # fix the indices
# return -1 if the indices are different when strings are reversed
return [indexes[i] + 1 if indexes[i] == indexesreversed[i] else - 1 for i in range(0, len(indexes))]
if __name__ == "__main__":
print theCards(495, list("RBRRBRBBRBRRBBRRBBBRRBBBRR"))