了解Big O以对数组中的元素进行平方

时间:2019-02-06 22:24:18

标签: arrays algorithm data-structures big-o

我正在解决一个问题,您必须将数字在leetcode上的排序数组中平方。这是原始问题

  

给出一个以非降序排序的整数数组,返回每个数字的平方的数组,也以非降序排序。

我试图理解我的代码和解决方案中给出的代码的大“ O”字样。

这是我的代码

def sortedSquare(A):
    new_A = []
    for num in A:
        num = num*num
        new_A.append(num)
    return sorted(new_A)


print(sortedSquare([-4, -1, 0, 3, 10]))

这是解决方案中的代码:

def sortedSquares(self, A):
    return sorted(x*x for x in A)

对于解决方案,Big O是

NlogN

其中N是数组的长度。我不明白为什么大O会是logN而不是N?

对于我的解决方案,我将其视为N的大O,因为我只是遍历整个数组。

而且,与给出的解决方案相比,我的解决方案是一个好的解决方案吗?

3 个答案:

答案 0 :(得分:4)

您的解决方案与给定的解决方案完全相同。两种解决方案都对所有元素求平方,然后对结果数组进行排序,而leetcode解决方案则更为简洁。

这两个解决方案之所以是O(NlogN)的原因是因为使用了sorted()。 Python的内置排序是timsort,它可以O(NlogN)的时间对数组进行排序。使用sorted()而不是平方是导致时间复杂度(O(NlogN) + O(N) = O(NlogN))的主要因素。

请注意,尽管可以在O(N)中使用两个指针或通过mergesort中的合并步骤来解决此问题。

编辑:

戴维·艾森斯塔特(David Eisenstat)在调音方面提出了非常好的观点。 Timsort汇总严格增加和严格减少的运行并将其合并。由于所得的平方数组将首先严格减少然后严格增加,因此timsort实际上会反转严格减少的行程,然后将它们合并到O(N)中。

答案 1 :(得分:1)

复杂度的工作方式是整个程序的整体复杂度是任何一部分的最坏的复杂度。因此,在您的情况下,您需要对数字进行平方运算,并对数字进行排序。那么确定整体复杂性的是哪一部分呢?

平方部分为o(n),因为您只需触摸一次元素即可使它们平方。

那排序部分呢?通常,这取决于您使用哪种排序功能:

  • 大多数排序例程都使用O(n * log(n)),因为它们使用分而治之的算法。
  • 有些(例如气泡排序)的O(n ^ 2)
  • 有些(如计数排序)的O(n)

在您的情况下,他们说给定解为O(n * log(n)),并且由于平方部分为O(n),因此排序部分必须为O(n * log(n))。并且由于您的代码使用与给定解决方案相同的排序功能,因此您的排序也必须为O(n * log(n))

因此,您的平方部分是O(n),而您的排序部分是O(n * log(n)),总体复杂度是最差的:O(n * log(n))

答案 2 :(得分:1)

如果允许额外的存储空间(如您的解决方案中所述),则整个过程可以在时间O(N)内执行。初始数组已排序。您可以将其分为带有负值和正值的两个子序列。

平方所有元素(O(N))并反转负子序列(更糟糕的是O(N)),以便对两个序列进行排序。如果其中一个子序列为空,则操作完成。

否则,按时间O(N)合并两个序列(这是使用额外O(N)空间的步骤)。