对于Leetcode的前k个常见问题,我有以下代码。
允许的时间限制复杂度小于o(nlogn)
,其中n是数组大小
我O
的大o(n)
复杂性不是吗?
如果是这样,为什么我还超过时间限制?
def topKFrequent(self, nums, k):
output = {}
outlist = []
for item in nums:
output[item] = nums.count(item)
max_count = sorted(output.values(),reverse= True)[:k]
for key,val in output.items():
if val in max_count:
outlist.append(key)
return (outlist)
testinput:数组[1,1,1,2,2,3,1,1,1,2,2,3] k = 2
测试输出: [1,2]
答案 0 :(得分:2)
由于以下原因,您的解决方案是O(n^2)
:
for item in nums:
output[item] = nums.count(item)
对于数组中的每个项目,您都在浏览整个数组以计算相同元素的数量。
您可以通过迭代O(n)
并将{1}添加到您发现的每个项目的计数器中来获得nums
中的计数。
最后的O(n log n)
将来自sorted(output.values(), reverse=True)
,因为每种通用排序算法(包括Timsort)都将是O(n log n)
。
答案 1 :(得分:1)
另一个答案提到,您的计数是O(n^2)
的时间复杂度,这导致您超过了时间限制。幸运的是,python在Counter
模块中带有一个collections
对象,该对象将完全按照其他答案的描述进行操作,但使用的是经过优化的C代码。这样会将您的时间复杂度降低到O(nlogn)
。
此外,您可以通过使用最小堆技巧来代替排序调用,从而将时间复杂度降低到O(nlogk)
。保持大小为k
的最小堆,然后添加其他元素并逐个弹出最小堆,直到所有元素都插入(在某个点或另一点)。堆中剩余的k
是您的最大k
值。
from collections import Counter
from heapq import heappushpop, heapify
def get_most_frequent(nums, k):
counts = Counter(nums)
counts = [(v, k) for k, v in counts.items()]
heap = counts[:k]
heapify(heap)
for count in counts[k:]:
heappushpop(heap, count)
return [k for v, k in heap]
如果必须以任何特定顺序返回元素,则可以在k
时间对O(klogk)
元素进行排序,这仍然会导致总体上具有相同的O(nlogk)
时间复杂度。