--- tags: data_structure_python --- # Top K Frequent Elements <img src="https://img.shields.io/badge/-medium-orange"> 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. - It's guaranteed that the answer is unique, in other words the set of the top k frequent elements is unique. - You can return the answer in any order. # Solution ```python= class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: # Time complexity: O(n) # Space complexity: O(n) bag = {} for elt in nums: if elt not in bag: bag[elt] = 1 else: bag[elt] += 1 # Index of array = frequencies freq = [[] for i in range(len(nums) + 1)] for key, val in bag.items(): freq[val].append(key) res = [] i, n = 0, len(freq) while i < n and k != 0: if len(freq[n-1-i]) > 0: res += freq[n-1-i] k -= len(freq[n-1-i]) i += 1 return res ``` ## Solution 1: Priority Queue using Heap ```python= class Solution: import heapq def topKFrequent(self, nums: List[int], k: int) -> List[int]: # N = # of elt in nums # k = size of heap. # Time complexity: O(Nlog(k)). # Space complexity: O(N+k) # 1. build hash map : character and how often it appears # O(N) time hashmap = {} for elt in nums: if elt in hashmap: hashmap[elt] += 1 else: hashmap[elt] = 1 # 2-3. build heap of top k frequent elements and # convert it into an output array # O(N log k) time return heapq.nlargest(k, hashmap.keys(), key=hashmap.get) ``` # Solution 2: Using divide and conquer approach (quicksort like) - Doesn't seem to work on a very large amount of numbers. Investigate why: https://leetcode.com/problems/top-k-frequent-elements/discuss/685786/why-is-my-code-not-working-on-the-very-last-test-case-huge-one ```python= class Solution: def partition(self, L, frequency, lo, hi, k): if len(L) == k: return L else: pivot, i, j = lo, lo, hi while i < j: while i < hi and frequency[L[i]] <= frequency[L[pivot]]: i += 1 while j > lo and frequency[L[j]] >= frequency[L[pivot]]: j -= 1 if i < j: L[i], L[j] = L[j], L[i] L[pivot], L[j] = L[j], L[pivot] rightPart = L[pivot+1:] return self.partition(rightPart, frequency, 0, len(rightPart)-1, k) def topKFrequent(self, nums: List[int], k: int) -> List[int]: # N = # of elt in nums # k = size of heap. # Time complexity: O(N). # Space complexity: O(N) # 1. build hash map : character and how often it appears # and array of unique elements. # O(N) time hashmap = {} unq_elts = [] for elt in nums: if elt in hashmap: hashmap[elt] += 1 else: hashmap[elt] = 1 unq_elts.append(elt) # 2. Choose a random pivot and put it in its place in a sorted array rightPart = self.partition(unq_elts, hashmap, 0, len(unq_elts)-1, k) # 3. Return the k most frequent elements from the right part array. return rightPart ```