【问题标题】:O(N) Time complexity for simple Python function简单 Python 函数的 O(N) 时间复杂度
【发布时间】:2017-11-16 16:00:16
【问题描述】:

我刚刚参加了 Codility 演示测试。 question and my answer can be seen here,但我也会在这里粘贴我的答案。我的回应:

def solution(A):
    # write your code in Python 2.7

    retresult = 1; # the smallest integer we can return, if it is not in the array

    A.sort()
    for i in A:
        if i > 0:
            if i==retresult:   retresult += 1 # increment the result since the current result exists in the array
            elif i>retresult:   break # we can go out of the loop since we found a bigger number than our current positive integer result


    return retresult

我的问题是关于时间复杂度的,我希望通过您的回答能更好地理解这一点。该问题要求预期的最坏情况时间复杂度为 O(N)

我的函数是否具有 O(N) 时间复杂度?我对数组进行排序这一事实是否会增加复杂性,如果是,如何增加?

Codility 报告(供我回答)

Detected time complexity: 
O(N) or O(N * log(N))

那么,我的函数的复杂性是多少?如果是 O(N*log(N)),我该怎么做才能将复杂度降低到 O(N)?

非常感谢!

附言我对时间复杂度的背景阅读来自this great post

编辑

在下面的回复和the answers described here for this problem 之后,我想用我对解决方案的看法对此进行扩展:

basicSolution 具有昂贵的时间复杂度,因此不是此 Codility 测试的正确答案:

def basicSolution(A):
    # 0(N*log(N) time complexity

    retresult = 1; # the smallest integer we can return, if it is not in the array

    A.sort()
    for i in A:
        if i > 0:
            if i==retresult:   retresult += 1 #increment the result since the current result exists in the array
            elif i>retresult:   break # we can go out of the loop since we found a bigger number than our current positive integer result
        else:
            continue; # negative numbers and 0 don't need any work

    return retresult

hashSolution 是我对上述文章“使用散列”段落中描述的内容的看法。由于我是 Python 新手,如果您对这段代码有任何改进(尽管它确实适用于我的测试用例),请告诉我,它的时间复杂度是多少?

def hashSolution(A):
    # 0(N) time complexity, I think? but requires 0(N) extra space (requirement states to use 0(N) space

    table = {}

    for i in A:
        if i > 0:
            table[i] = True # collision/duplicate will just overwrite

    for i in range(1,100000+1): # the problem says that the array has a maximum of 100,000 integers
        if not(table.get(i)): return i

    return 1 # default

最后,我无法理解实际的 0(N) 解决方案(O(n) 时间和 O(1) 额外空间解决方案)。我知道负/ 0 值被推到数组的后面,然后我们有一个只有正值的数组。但我不明白 findMissingPositive 功能 - 任何人都可以用 Python 代码/cmets 描述这个吗?也许举个例子?我一直在尝试在 Python 中解决它,但无法弄清楚:(

【问题讨论】:

    标签: python time-complexity


    【解决方案1】:

    它没有,因为你排序A

    Python list.sort() 函数使用 Timsort(以 Tim Peters 命名),并且具有 O(NlogN) 的最坏情况时间复杂度。

    您不必对输入进行排序,而是必须对其进行迭代并通过其他方式确定是否缺少任何整数。我会使用一组range() 对象:

    def solution(A):
        expected = set(range(1, len(A) + 1))
        for i in A:
            expected.discard(i)
        if not expected:
            # all consecutive digits for len(A) were present, so next is missing
            return len(A) + 1
        return min(expected)
    

    这是 O(N);我们创建了一组len(A)(O(N) 时间),然后我们循环 A,从 expected 中删除元素(再次 O(N) 时间,从集合中删除元素是 O(1)),然后测试expected是否为空(O(1)次),最后得到expected中最小的元素(最多O(N)次)。

    所以我们在上面的函数中最多做 3 个 O(N) 的时间步,使它成为一个 O(N) 的解决方案。

    这也符合存储要求;所有使用都是一个大小为 N 的集合。集合的开销很小,但总是小于 N。

    您找到的哈希解决方案基于相同的原理,只是它使用字典而不是集合。请注意,字典值从未实际使用过,它们要么设置为True,要么不存在。我将其重写为:

    def hashSolution(A):
        seen = {i for i in A if i > 0}
        if not seen:
            # there were no positive values, so 1 is the first missing.
            return 1
        for i in range(1, 10**5 + 1):
            if i not in seen:
                return i
        # we can never get here because the inputs are limited to integers up to
        # 10k. So either `seen` has a limited number of positive values below
        # 10.000 or none at all.
    

    如果A 中没有正整数,则上述内容可避免一直循环到 10.000。

    我的和他们的不同之处在于,我的从一组期望的数字开始,而他们从A的一组正值开始,反转存储和测试。

    【讨论】:

    • 非常感谢您的回复,我现在了解 list.sort() 的时间复杂度部分。不过,对于实际的解决方案,我不确定这是否是针对原始问题的。如果是的话,请原谅我,但你能看看我帖子中上面的编辑,让我知道你的想法吗?具体来说,非常感谢您对 hashSolution 的回复以及您对 findMissingPositive 函数的看法。谢谢!
    • @rishijd:我用所有样本输入测试了我的解决方案,它为所有这些提供了正确的解决方案。这是一个有效的解决方案。
    • @rishijd:哈希解决方案和我给出的解决方案一样,只是使用带有True 的字典来模拟一个集合。他们颠倒了存储和测试,仅此而已。
    • 非常感谢 Martijn,太棒了!我必须自己玩这个函数才能意识到为什么“预期”有效:) 最后一个问题 - 我仍在尝试理解 solution() 与 hashSolution() 的空间复杂度。我理解 hashSolution,时间:O(N)。 “seen”集合的创建 = 0(N),然后我们检查 if not seen = O(1),然后我们经过一个大范围 O(100000+1) - 即 O(N)。那是对的吗?空间:需要 O(N) 额外空间? hashSolution 和 solution 是否需要相同的空间?只是想通过这些示例了解我对空间复杂度的理解是否正确。
    猜你喜欢
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2013-10-20
    相关资源
    最近更新 更多