为什么我的限制超出了前k个常见问题[LEETCODE]?

时间:2019-03-04 23:30:37

标签: python algorithm data-structures

对于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]

问题链接:https://leetcode.com/problems/top-k-frequent-elements/

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)时间复杂度。