找到带有O(1)空格和O(n)时间

时间:2017-09-14 14:06:29

标签: python algorithm data-structures

我在leetcode中解决了一个问题

给定包含n + 1个整数的数组nums,其中每个整数在1和n之间(包括1和n),证明必须存在至少一个重复的数字。假设只有一个重复的数字,在O(n)时间和O(1)空间复杂度中找到重复的数字

class Solution(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        xor=0
        for num in nums:
            newx=xor^(2**num)
            if newx<xor:
                return num
            else:
                xor=newx

我接受了解决方案,但我被告知它既不是O(1)空间也不是O(n)时间。

任何人都可以帮我理解为什么吗?

2 个答案:

答案 0 :(得分:6)

你的问题实际上很难回答。通常在处理复杂性时,会假设机器模型。 A standard model假设当输入大小为n时,内存位置的大小为log(n)位,而对log(n)位大小的数字的算术运算为O(1)。

在此模型中,您的代码在空间中不是O(1),在时间上不是O(n)。你的xor值有n位,这不适合常量内存位置(它实际上需要n / log(n)内存位置。同样,它不是O(n)及时,因为算术运算是在大于log(n)位的数字上。

要在O(1)空间和O(n)时间内解决您的问题,您必须确保您的值不会太大。一种方法是xor数组中的所有数字,然后你会得到1^2^3...^n ^ d,其中d是重复的。因此,您可以从数组的总xor中xor 1^2^3^..^n,并找到重复的值。

def find_duplicate(ns):
    r = 0
    for i, n in enumerate(ns):
        r ^= i ^ n
    return r

print find_duplicate([1, 3, 2, 4, 5, 4, 6])

这是O(1)空间,而r以来的O(n)时间从不使用比n更多的位(即大约ln(n)位)。

答案 1 :(得分:0)

您的解决方案不是O(1)空格,意思是:您的空间/内存不是常量,但取决于输入!

newx=xor^(2**num)

这是log_2(2**num) = num位的逐位XOR,其中num是您的输入数字之一,导致log_2(2**num) = num位结果。

所以n=10 = log_2(2^10) = 10 bitsn=100 = log_2(2^100) = 100 bits。它呈线性增长(不恒定)。

你得到的时间复杂度也不在O(n)之内:

  • 所有n个数字的外部循环
    • 和非常数/非O(1)内环(见上文)
    • 假设:关于输入的位表示,XOR不是常数
      • 并不总是这样对待;但物理学支持这种主张(Chandrasekhar限制,光速,......)