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:
- You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
- 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