347. Top K Frequent Elements [medium] (Python)

题目链接

https://leetcode.com/problems/top-k-frequent-elements/

题目原文

Given a non-empty array of integers, return the k most frequent elements.

For example,
Given [1,1,1,2,2,3] and k = 2, return [1,2].

Note:

  1. You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  2. Your algorithm’s time complexity must be better than O(n log n), where n is the array’s size.

思路方法

解这个题的关键在于控制时间复杂度“小于O(nlogn)”这个条件。

思路一

按照我的思维习惯,看到这个题,首先想到的是下面的思路:先用dict得到所有不同数的个数;再对个数排序,取前k个个数最多的对应的数即可。代码如下,然而使用了内置sorted()函数,只能说时间复杂度小于等于O(nlogn),不太满足题意的样子,仅供参考。【时间复杂度O(nlogn)】

代码

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        data, res = {}, []
        for i in nums:
            data[i] = data[i] + 1 if i in data else 1
        sorted_data = sorted(data.iteritems(), key=operator.itemgetter(1), reverse=True)
        for i in xrange(k):
            res.append(sorted_data[i][0])
        return res

思路二

在上面思路的基础上,通过改进排序步骤改善时间复杂度。考虑使用时间复杂度只有O(n)的桶排序(bucket sort),同时消耗空间复杂度O(n)。代码如下。【时间复杂度O(n)】

代码

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        data, res = {}, []
        for i in nums:
            data[i] = data[i] + 1 if i in data else 1
        bucket = [[] for i in xrange(len(nums)+1)]
        for key in data:
            bucket[data[key]].append(key)
        for i in xrange(len(bucket)-1, -1, -1):
            if bucket[i]:
                res.extend(bucket[i])
            if len(res) >= k:
                break
        return res[:k]

思路三

还是沿着思路一,除了桶排序,优先队列也是可以满足要求的解法。很多语言都有内建优先队列结构,在Python里有Queue.PriorityQueue,也有更高效的heapq(用list模拟heap),这里使用heapq。【时间复杂度O(nlogk)】
注:由于heapq默认是最小堆,代码中在堆的push时给权重加了负号,这样堆顶部对应的实际上是出现次数最多的数。

代码

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        data, res, pq = {}, [], []
        for i in nums:
            data[i] = data[i] + 1 if i in data else 1
        for key in data:
            heapq.heappush(pq, (-data[key], key))
        for i in xrange(k):
            res.append(heapq.heappop(pq)[1])
        return res

思路四

其实,单纯解决这种计数问题的话,Python的很多内置函数都很方便,但内部的实现我并不清楚,这里写一下仅供增长姿势 :)

代码一

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        counter = collections.Counter(nums)
        return [item[0] for item in counter.most_common(k)]

代码二

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        counter = collections.Counter(nums)
        return heapq.nlargest(k, counter, key=lambda x: counter[x])

PS: 写错了或者写的不清楚请帮忙指出,谢谢!
转载请注明:http://blog.csdn.net/coder_orz/article/details/52075042

你可能感兴趣的:(LeetCode,LeetCode解题报告)