【发布时间】:2021-04-05 14:53:16
【问题描述】:
您好,我正在练习 leetcode 的编码测试,我有一个问题。
“26. Remove Duplicates from Sorted Array”描述如下。
给定一个排序数组 nums,就地删除重复项,使每个元素只出现一次并返回新的长度。不要为另一个数组分配额外的空间,您必须通过使用 O(1) 额外内存就地修改输入数组来做到这一点。
解决方案 01
# 4.4948496559999995
idx = 0
for _ in range(len(nums)-1):
if nums[-1-idx] == nums[-2-idx]:
nums.pop(-1-idx)
else:
idx += 1
return len(nums)
解决方案 02
# 3.689027874
ans = 1
for i in range(len(nums)-1):
if nums[i] != nums[i+1]:
nums[ans] = nums[i+1]
ans += 1
return ans
检查时间复杂度
if __name__ == '__main__':
from timeit import Timer
t = Timer("for t in [[1, 1, 1, 2], [1, 1, 1, 2, 2, 3], [1, 2, 3, 3, 3, 3], []]: Solution().removeDuplicates(t)", "from __main__ import Solution")
print(t.timeit())
解决方案 01 运行时间为 4.4948496559999995,解决方案 02 运行时间为 3.689027874
pop 和 index 的时间复杂度为 O(1),但为什么解决方案 02 比解决方案 01 快?
【问题讨论】:
-
对象属性查找和函数调用开销...
-
nums最后大小一样吗? -
pop是 O(1) 如果你弹出最后一个元素。 -
另外,您的解决方案 2 在列表末尾留下一堆垃圾 - 您必须删除这些垃圾。 (切片删除是合适的。)
-
关于
pop,wiki.python.org/moin/TimeComplexity 表示:“[2] = 从大小为 n 的列表中弹出索引 k 处的中间元素,使用 memmove 将 k 之后的所有元素向左移动一个槽。 n - k 个元素必须被移动,所以操作是 O(n - k)。最好的情况是弹出倒数第二个元素,这需要一次移动,最坏的情况是弹出第一个元素,这涉及 n - 1移动。平均值 k 的平均情况是将元素弹出列表中间,这需要 O(n/2) = O(n) 操作。"