我正在研究leetcode算法问题977. Squares of a Sorted Array.
为什么使用内置方法对提交的邮件进行排序比下面的o(n)遍历方法快?
输入是一个带有整数的排序列表(非降序)。
提交208毫秒的示例:
class Solution:
def sortedSquares(self, A: List[int]) -> List[int]:
return sorted(x*x for x in A)
我的260毫秒提交时间:
class Solution:
def sortedSquares(self, A: List[int]) -> List[int]:
start = 0
end = len(A)-1
B = []
while start <= end:
if abs(A[start]) >= abs(A[end]):
B.append(A[start] * A[start])
start += 1
else:
B.append(A[end] * A[end])
end -= 1
B.reverse()
return B
答案 0 :(得分:2)
仅仅因为您的算法具有更好的最坏情况运行时间,并不意味着它在实践中会更好。 Python的内置排序方法经过高度优化,因此对于相对较小的C:/Strawberry/perl/lib
,其运行时间可以为cnlg(n)
,而算法为c
时,则可以具有非常高的常数{ O(n)
代表d
。我们不知道您的输入是什么,因此它可能是由10000个元素组成的数组,为此dn
仍然比d
大得多。
此外,由于您的输入列表是经过排序的(非负数部分),因此在这种情况下,可能会对近乎排序的列表进行一些优化(不确定,从来没有看过Python的sort实现)。
答案 1 :(得分:2)
LeetCode报告的时间是针对您的解决方案进行测试的所有测试用例的总和。作为算法效率的度量,这是非常不可靠的,因为
有关更多讨论,请参见this answer。
因此,如果我们想比较两种算法的性能,最好自己动手做。我做到了这是我的时间,最多可访问5,000个列表(每个平均运行1,000多个):
这是我的时代,不超过100万个列表的大小(无平均值):
如您所见,无论大小输入,使用sorted
的速度一直都比较快,因此这次LeetCode的比较实际上是正确的(尽管无论如何都是巧合!)。您的解决方案确实是线性时间,并且这些结果与之一致。但是使用sorted
的解决方案似乎也花费了线性时间,堆溢出的答案解释了这样做的原因。
我的计时代码如下。时间是使用Python 3.5.2进行测量的,而使用Python 3.8.1可获得类似的结果。
def linear(A):
start = 0
end = len(A)-1
B = []
while start <= end:
if abs(A[start]) >= abs(A[end]):
B.append(A[start] * A[start])
start += 1
else:
B.append(A[end] * A[end])
end -= 1
B.reverse()
return B
def using_sorted(A):
return sorted(x*x for x in A)
from timeit import timeit
from random import randint
print('n', 'linear', 'using sorted', sep='\t')
for n in range(10000, 1000001, 10000):
data = sorted(randint(-10*n, 10*n) for i in range(n))
t1 = timeit(lambda: linear(data), number=1)
t2 = timeit(lambda: using_sorted(data), number=1)
print(n, t1, t2, sep='\t')
答案 2 :(得分:1)
您可以对所有内容进行预平方(因此不需要abs()
,尤其是不需要重复的abs()
调用单个元素):
C = [x*x for x in A]
start = 0
end = len(A)-1
B = []
while start <= end:
if C[start] >= C[end]:
B.append(C[start])
start += 1
else:
B.append(C[end])
end -= 1
B.reverse()
return B
但是我还没有测量。例如,就地预平方可能会更好。
答案 3 :(得分:1)
使用Timsort的Python内置sorted
函数在这种情况下也是 O(n)!您的输入数字已排序并平方。让我们看一下三种情况:
[-5, -4, -2, -1]
变为[25, 16, 4, 1]
。 Timsort会检测到该情况,并简单地反转该列表。再次计时O(n)。所以...内置sorted
和您自己的排序都是O(n)。但是sorted
是在C级别实现的,它更快并且可以访问快捷方式,从而为它提供了一个较小的隐藏常量。
答案 4 :(得分:0)
这是因为Python使用Timsort,这是一种基于marge_sort和insert_sort的自适应排序算法。时间复杂度是
O(nlogn)
对于python中的Sorted()。
这就是为什么Sorted()比您的工作更快的原因