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

时间:2017-10-05 15:40:22

标签: python

给定一段以空格分隔的小写英文单词和一系列独特的小写英文关键字,找到子字符串的最小长度,其中包含按空格分隔的所有关键字。

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

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))

1 个答案:

答案 0 :(得分:0)

诀窍是从左向右扫描,一旦找到包含所有键的窗口,尝试在左侧缩小它并在右侧放大,保留所有术语保留在窗口内的属性。 / p>

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

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