LeetCode347:Top K Frequent Elements

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

Example 1:

Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]

Example 2:

Input: nums = [1], k = 1
Output: [1]

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.

LeetCode:链接

给定一个数组,返回其出现次数最多的k个元素,要求复杂度小于O(nlogn)。

1)首先扫一遍数组进行计数。接着用一个长度为k的最小堆,存储出现次数最多的元素(堆顶的元素最小,每次和堆顶的元素比较即可)。

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        countDict = {}
        for num in nums:
            countDict[num] = countDict.get(num, 0) + 1
        heap = []
        for key, value in countDict.items():
            if len(heap) < k:
                heap.append((key, value))
                length = len(heap)
                for i in range(0, length//2)[::-1]:
                    self.HeadAdjust(heap, i, length)
            else:
                if value > heap[0][1]:
                    heap.pop(0)
                    heap.insert(0, (key, value))
                    self.HeadAdjust(heap, 0, k)
        return [x[0] for x in heap]

    def HeadAdjust(self, nums, parent, length):
        temp = nums[parent][1]
        temp_node = nums[parent]
        child = 2 * parent + 1
        while child < length:
            if child + 1 < length and nums[child+1][1] < nums[child][1]:
                child += 1
            if temp <= nums[child][1]:
                break
            nums[parent] = nums[child]
            parent = child
            child = 2 * parent + 1
        nums[parent] = temp_node

也可以直接用heapq实现:

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        counts = collections.Counter(nums)
        heap = []
        for key, cnt in counts.items():
            if len(heap) < k:
                heapq.heappush(heap, (cnt, key))
            else:
                if heap[0][0] < cnt:
                    heapq.heappop(heap)
                    heapq.heappush(heap, (cnt, key))
        return [x[1] for x in heap]

2)考虑使用时间复杂度只有O(n)的桶排序(bucket sort),同时消耗空间复杂度O(n)。桶排序就是空间换时间。1.遍历数组nums,利用字典cntDict统计各元素出现次数。 2. 遍历cntDict,利用嵌套列表freqList记录出现次数为i( i∈[1, n] )的所有元素 3. 逆序遍历freqList,将其中的前k个元素输出。

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        countDict = {}
        res = []
        for num in nums:
            countDict[num] = countDict.get(num, 0) + 1
        bucket = [[] for i in range(len(nums)+1)]
        # 遍历字典 将key按照出现的次数放到对应的索引上 所以index5放了1 就说明1出现了5次
        for key in countDict:
            bucket[countDict[key]].append(key)
        # 从后往前遍历
        for i in range(len(bucket)-1, -1, -1):
            if bucket[i]:
                res.extend(bucket[i])
            if len(res) >= k:
                break
        return res[:k]

猜你喜欢

转载自blog.csdn.net/mengmengdajuanjuan/article/details/86172450