如何降低python的时间复杂度?

如何降低python的时间复杂度?,python,Python,给定一段空格分隔的小写英语单词和一个唯一的小写英语关键字列表,找出其子字符串的最小长度,该子字符串包含按任何顺序由空格分隔的所有关键字 我把下面的代码放在哪里是错误?如何降低时间复杂度 import sys def minimumLength(text, keys): answer = 10000000 text += " $" for i in xrange(len(text) - 1): dup = list(keys) word =

给定一段空格分隔的小写英语单词和一个唯一的小写英语关键字列表,找出其子字符串的最小长度,该子字符串包含按任何顺序由空格分隔的所有关键字

我把下面的代码放在哪里是错误?如何降低时间复杂度

import sys
def minimumLength(text, keys):
    answer = 10000000
    text += " $"
    for i in xrange(len(text) - 1):
        dup = list(keys)
        word = ""
        if i > 0 and text[i - 1] != ' ':
            continue

        for j in xrange(i, len(text)):
            if text[j] == ' ':
                for k in xrange(len(dup)):
                    if dup[k] == word:
                        del(dup[k])
                        break
                word = ""
            else:
                word += text[j]
            if not dup:
                answer = min(answer, j - i)
                break

    if(answer == 10000000):
        answer = -1

    return answer
text = raw_input()
keyWords = int(raw_input())
keys = []
for i in xrange(keyWords):
    keys.append(raw_input())
print(minimumLength(text, keys))

诀窍是从左到右扫描,一旦找到一个包含所有键的窗口,尝试在左侧缩小它,在右侧放大它,保留所有项都保留在窗口内的属性

使用此策略,您可以在线性时间内解决任务。 以下代码是我在几个字符串上测试的代码草稿,我希望注释足以突出最关键的步骤:


def最小长度(文本、键):
断言isinstance(text,str)和(isinstance(key,set)或len(key)==len(set(key)))
最小长度=无
按键至occ=dict((k,0)表示k in按键)
text\u words=[word if word in key\u to\u occ else None for word in text.split()]
缺少单词=len(键)
左位置,最后一个右位置=0,0
#找到一个包含所有键的间隔
对于右位置,枚举中的右单词(文本单词):
如果“右”字为“无”:
持续
按键至occ[右键]+=1
occ_word=按键至occ[右键]
如果occ_word==1:#我们在当前时间间隔内第一次看到这个单词
缺少单词-=1
如果缺少单词==0:#我们看到了此间隔中的所有单词
按键至occ[右字]-=1
最后一个右位置=右位置
打破
如果缺少>0的单词:
一无所获
#减少左侧的间隔,并在右侧扩大间隔,以保留所有关键点都在其中的属性
对于xrange中的右位置(最后一个右位置,len(文本字)):
右单词=文本单词[右位置]
如果“右”字为“无”:
持续
按键至occ[右键]+=1
而left_pos
这具有学校作业的所有特征。这类问题在这里通常不受欢迎。如果您要发布代码,请提供代码不起作用的原因。谢谢。@Torxed-不管这是不是学校作业,重要的是问题要遵循指导原则。另外,既然问题是关于时间复杂度的,你能告诉我们你对时间复杂度的计算,以及你的确切问题是什么吗?提示:您正在使用三个for循环,其中两个将转到
n
def minimum_length(text, keys):
    assert isinstance(text, str) and (isinstance(keys, set) or len(keys) == len(set(keys)))
    minimum_length = None
    key_to_occ = dict((k, 0) for k in keys)
    text_words = [word if word in key_to_occ else None for word in text.split()]
    missing_words = len(keys)
    left_pos, last_right_pos = 0, 0

    # find an interval with all the keys
    for right_pos, right_word in enumerate(text_words):
        if right_word is None:
            continue
        key_to_occ[right_word] += 1
        occ_word = key_to_occ[right_word]
        if occ_word == 1:  # the first time we see this word in the current interval
            missing_words -= 1
            if missing_words == 0:  # we saw all the words in this interval
                key_to_occ[right_word] -= 1
                last_right_pos = right_pos
                break

    if missing_words > 0:
        return None

    # reduce the interval on the left and enlarge it on the right preserving the property that all the keys are inside
    for right_pos in xrange(last_right_pos, len(text_words)):
        right_word = text_words[right_pos]
        if right_word is None:
            continue
        key_to_occ[right_word] += 1
        while left_pos < right_pos:  # let's try to reduce the interval on the left
            left_word = text_words[left_pos]
            if left_word is None:
                left_pos += 1
                continue
            if key_to_occ[left_word] == 1:  # reduce the interval only if it doesn't decrease the number of occurrences
                interval_size = right_pos + 1 - left_pos
                if minimum_length is None or interval_size < minimum_length:
                    minimum_length = interval_size
                break
            else:
                left_pos += 1
                key_to_occ[left_word] -= 1
    return minimum_length