代码改变世界

[LeetCode] 347. Top K Frequent Elements_Medium tag: Array, Heap, quickSort

2021-06-28 09:51  Johnson_强生仔仔  阅读(45)  评论(0编辑  收藏  举报

Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.

 

Example 1:

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

Example 2:

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

 

Constraints:

  • 1 <= nums.length <= 105
  • k is in the range [1, the number of unique elements in the array].
  • It is guaranteed that the answer is unique.

 

Follow up: Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

Ideas:

1. 利用collections.Counter(), 得到num: countNum 的dictionary, 再将它根据countNum来排序,取前面k个即可。

n = len(nums),   m = len(distinct number )

T: O(m * lgm)      S: O(m)

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        d = collections.Counter(nums)
        ans, freqs = [], sorted([(d[num], num) for num in d], reverse = True)
        for i in range(k):
            ans.append(freqs[i][1])
        return ans

 

1.2 利用dictionary的built-in function, most_common(k)

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        return [k for k, v in Counter(nums).most_common(k)]

1.3 more fency..

 

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        return zip(*Counter(nums).most_common(k))[0]

 

 

2. 利用heap和python的heapq.nlargest()method

T: O(n * lgk)   S: O(k)

class Solution(object):
    def topKFrequent(self, nums, k):
        """ Given a non-empty array of integers, return the k most frequent elements.

        heapq.nlargest(n, iterable[, key])
        Return a list with the n largest elements from the dataset defined by iterable.
        """
        count = collections.Counter(nums)
        return heapq.nlargest(k, count, key=lambda x: count[x])

 

3. Use quickSort, 其实跟[LeetCode] 973. K Closest Points to Origin_Medium tag: Sort, heap, quickSort做法一样。

T: average O(n), worst case O(n ^ 2)

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count = collections.Counter(nums)
        uniques = list(set(nums))
        n = len(uniques)
        l, r = 0, n - 1
        while l < r:
            index = self.partition( uniques, count, l, r)
            if index == n - k:
                break
            elif index < n - k:
                l = index + 1
            else:
                r = index - 1
        return uniques[n - k:]
    
    def partition(self, uniques, count, l, r):
        pivot = uniques[r]
        index = l
        for i in range(l, r):
            if self.compare(count, uniques[i], pivot) < 0:
                uniques[index], uniques[i] = uniques[i], uniques[index]
                index += 1
        uniques[index], uniques[r] = uniques[r], uniques[index]
        return index
        
    
    
    def compare(self, d, index1, index2):
        return d[index1] - d[index2]

 

4. Update in 10/24/2023 It is like counting sort, 得到最大的freq的数,然后将freq里面的list加入到ans里面,最后返回ans[:k]

T: O(n) S: O(n)

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        d = collections.Counter(nums)
        countList = collections.defaultdict(list)
        largestCount = 0
        for num in d:
            countList[d[num]].append(num)
            largestCount = max(largestCount, d[num])
        
        ans = []
        for i in range(largestCount, 0, -1):
            ans.extend(countList[i])
            if len(ans) >= k:
                break
        return ans[:k]