Arrays 了解数组中元素平方的大O

Arrays 了解数组中元素平方的大O,arrays,algorithm,data-structures,big-o,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) pri

我正在研究一个问题,在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)
对于解决方案,最大的问题是

NlogN
其中N是数组的长度。我不明白为什么对大O来说是logN而不仅仅是N

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


另外,与给出的解决方案相比,我的解决方案是否是一个好的解决方案?

您的解决方案与给出的解决方案做的事情完全相同。这两种解决方案都将所有元素平方,然后对结果数组进行排序,leetcode解决方案更简洁一些

这两种解决方案都是ONlogN的原因是使用了sorted。Python的内置排序是在ONlogN时间内对数组进行排序。使用排序而不是平方运算是时间复杂度的主导因素ONlogN+ON=ONlogN

但是请注意,这个问题可以通过使用两个指针或使用mergesort中的merge步骤来解决

编辑:


大卫·艾森斯塔(David Eisenstat)在提姆索特(timsort)问题上提出了一个非常好的观点。Timsort严格增加和减少运行,并合并它们。由于生成的平方数组将首先严格递减,然后严格递增,因此timsort实际上会反转严格递减运行,然后将它们合并到上。

您的解决方案与给定的解决方案执行完全相同的操作。这两种解决方案都将所有元素平方,然后对结果数组进行排序,leetcode解决方案更简洁一些

这两种解决方案都是ONlogN的原因是使用了sorted。Python的内置排序是在ONlogN时间内对数组进行排序。使用排序而不是平方运算是时间复杂度的主导因素ONlogN+ON=ONlogN

但是请注意,这个问题可以通过使用两个指针或使用mergesort中的merge步骤来解决

编辑:


大卫·艾森斯塔(David Eisenstat)在提姆索特(timsort)问题上提出了一个非常好的观点。Timsort严格增加和减少运行,并合并它们。由于生成的平方数组将首先严格递减,然后严格递增,因此timsort实际上会反转严格递减的运行,然后将它们合并到一起。

复杂度的工作方式是,整个程序的总体复杂度是任何一个部分的最差复杂度。所以,在你的例子中,你有一部分是对数字进行平方,还有一部分是对数字进行排序。那么,哪一部分决定了整体的复杂性呢

“平方”部分处于启用状态,因为您只需触摸元素一次即可使其平方

分拣部分呢?通常,这取决于您使用的排序功能:

大多数排序例程都有On*logn,因为它们使用分治算法。 一些像冒泡排序的已经在^2上了 有些人喜欢数数的方式 在您的例子中,他们说给定的解决方案在*logn上,因为平方部分在*logn上,所以排序部分必须在*logn上。由于您的代码使用与给定解决方案相同的排序函数,因此您的排序也必须在*logn上


因此,平方部分打开,排序部分打开*logn,总体复杂度是其中最差的:在*logn上,复杂度的工作方式是,整个程序的总体复杂度是任何一个部分的最差复杂度。所以,在你的例子中,你有一部分是对数字进行平方,还有一部分是对数字进行排序。那么,哪一部分决定了整体的复杂性呢

“平方”部分处于启用状态,因为您只需触摸元素一次即可使其平方

分拣部分呢?通常,这取决于您使用的排序功能:

大多数排序例程都有On*logn,因为它们使用分治算法。 一些像冒泡排序的已经在^2上了 有些人喜欢数数的方式 在您的例子中,他们说给定的解决方案在*logn上,因为平方部分在*logn上,所以排序部分必须在*logn上。由于您的代码使用与给定解决方案相同的排序函数,因此您的排序也必须在*logn上


因此,平方部分打开,排序部分打开*logn,总体复杂度是其中最差的:在*logn上

如果像解决方案中一样允许额外的存储空间,则整个过程可以及时执行。初始数组已排序。您可以使用负值和正值将其拆分为两个子序列

将所有元素平方并反转负子元素 顺序在更坏的情况下打开,以便对两个顺序进行排序。如果其中一个子序列为空,则完成


否则,请及时合并这两个序列。这是使用额外ON空间的步骤。

如果像解决方案中一样允许额外的存储空间,则整个过程可以及时执行。初始数组已排序。您可以使用负值和正值将其拆分为两个子序列

将所有元素平方为开,并将负子序列反转为开,以便对两个序列进行排序。如果其中一个子序列为空,则完成


否则,合并两个序列,在时间上,这是一个使用额外空间的步骤。

我不记得timsort是如何工作的,但它有可能检测到平方数组的双音性,并将排序的运行与反向排序的运行合并。@Davidisenstat你说得对。我真的很震惊,它的算法是多么的聪明。我不记得timsort是如何工作的,但它有可能检测到平方数组的双单调性,并将排序运行与反向排序运行合并。@Davidisenstat你说得对。老实说,我震惊了,这个算法真是太聪明了。它甚至可以就地执行。如果你从两端开始向内移动,按需要两两交换,甚至可能在一次传递中——尽管我需要更详细地考虑问题以确定。@KonradRudolph:就地合并是可能的,但非常复杂交换的想法不起作用。阅读实用就地合并,BING-CHAO HUANG和MICHAEL A.LANGSTON,你可以在网上找到。一般来说,是的,我以前自己也实现过就地合并排序,我不推荐。但在这种情况下?@KonradRudolph:都不是。如果您实现了就地合并,您应该知道。这甚至可以就地执行。如果你从两端开始向内移动,按需要两两交换,甚至可能在一次传递中——尽管我需要更详细地考虑问题以确定。@KonradRudolph:就地合并是可能的,但非常复杂交换的想法不起作用。阅读实用就地合并,BING-CHAO HUANG和MICHAEL A.LANGSTON,你可以在网上找到。一般来说,是的,我以前自己也实现过就地合并排序,我不推荐。但在这种情况下?@KonradRudolph:都不是。如果您实现了就地合并,您应该知道。