Given an array arr[] and a positive integer k, Find the top k elements which have the highest frequency in the array.
Note: If more than one element has same frequency then priorities the larger element over the smaller one.
Examples:
Input: arr[] = [3, 1, 4, 4, 5, 2, 6, 1], k = 2
Output: [4, 1]
Explanation: Frequency of 4 is 2 and frequency of 1 is 2, these two have the maximum frequency.Input: arr[] = [7, 10, 11, 5, 2, 5, 5, 7, 11, 8, 9], k = 4
Output: [5, 11, 7, 10]
Explanation: Frequency of 5 is 3, frequency of 11 is 2, frequency of 7 is 2, and frequency of rest is 1 but 10 is largest .
Table of Content
[Naive Approach] Using Hash map and Sorting
The idea is to use a hashmap to store each element along with its frequency, allowing insertion and updates in constant time. After building the frequency map, sort the elements in decreasing order of their frequency. To find the top k elements, simply take the first k elements from the sorted list.
//Driver Code Starts
#include <iostream>
#include <unordered_map>
#include <algorithm>
#include <vector>
using namespace std;
//Driver Code Ends
// Comparison function to sort the frequency array
static bool compare(pair<int, int> &p1, pair<int, int> &p2) {
// Prioritise element's value incase their frequency was same
if (p1.second == p2.second)
return p1.first > p2.first;
// Sort on the basis of decreasing order
// of frequencies
return p1.second > p2.second;
}
// Function to find k numbers with most occurrences
vector<int> topKFreq(vector<int>&arr,int k) {
int n = arr.size();
unordered_map<int, int> mp;
for (int i = 0; i < n; i++)
mp[arr[i]]++;
// Store the elements of 'mp' in the vector 'freq'
vector<pair<int, int>> freq(mp.begin(), mp.end());
// Sort the vector 'freq' on the basis of the
// 'compare' function
sort(freq.begin(), freq.end(), compare);
vector<int>res;
// Extract and store the top k frequent elements
for (int i = 0; i < k; i++)
res.push_back(freq[i].first);
return res;
}
//Driver Code Starts
int main() {
vector<int> arr = {3, 1, 4, 4, 5, 2, 6, 1};
int k = 2;
vector<int> res = topKFreq(arr, k);
for(int val : res)
cout << val << " ";
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
class GFG {
//Driver Code Ends
// Comparison function to sort the frequency array
static class Compare implements Comparator<int[]> {
public int compare(int[] p1, int[] p2) {
// Prioritise element's
//value in case their frequency was same
if (p1[1] == p2[1])
return Integer.compare(p2[0], p1[0]);
// Sort on the basis of decreasing order
// of frequencies
return Integer.compare(p2[1], p1[1]);
}
}
// Function to find k numbers with most occurrences
static ArrayList<Integer> topKFreq(int[] arr, int k) {
int n = arr.length;
Map<Integer, Integer> mp = new HashMap<>();
for (int i = 0; i < n; i++)
mp.put(arr[i], mp.getOrDefault(arr[i], 0) + 1);
// Store the elements of 'mp' in the list 'freq'
ArrayList<int[]> freq = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : mp.entrySet())
freq.add(new int[]{entry.getKey(), entry.getValue()});
// Sort the list 'freq' on the basis of the
// 'compare' function
freq.sort(new Compare());
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i < k; i++) {
res.add(freq.get(i)[0]);
}
return res;
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {3, 1, 4, 4, 5, 2, 6, 1};
int k = 2;
ArrayList<Integer> res = topKFreq(arr, k);
for (int val : res)
System.out.print(val + " ");
}
}
//Driver Code Ends
#Driver Code Starts
from collections import Counter
#Driver Code Ends
def topKFreq(arr, k):
n = len(arr)
mp = Counter(arr)
# Store the elements of 'mp' in the list 'freq'
freq = list(mp.items())
# Sort the list 'freq' on the basis of the
# 'compare' function
freq.sort(key=lambda x: (x[1], x[0]), reverse=True)
res = []
# Extract and store the top k frequent elements
for i in range(k):
res.append(freq[i][0])
return res
#Driver Code Starts
if __name__ == "__main__":
arr = [3, 1, 4, 4, 5, 2, 6, 1]
k = 2
res = topKFreq(arr, k)
for val in res:
print(val, end=" ")
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
using System.Linq;
class GFG {
//Driver Code Ends
// Comparison function to sort the frequency array
class FrequencyComparer : IComparer<int[]> {
public int Compare(int[] p1, int[] p2) {
// Prioritise element's value
// in case their frequency is same
if (p1[1] == p2[1])
return p2[0].CompareTo(p1[0]);
// Sort on the basis of decreasing order
// of frequencies
return p2[1].CompareTo(p1[1]);
}
}
// Function to find k numbers with most occurrences
static List<int> topKFreq(int[] arr, int k) {
int n = arr.Length;
Dictionary<int, int> mp = new Dictionary<int, int>();
foreach (int num in arr) {
if (mp.ContainsKey(num))
mp[num]++;
else
mp[num] = 1;
}
// Store the elements of 'mp' in the list 'freq'
List<int[]> freq = new List<int[]>();
foreach (var entry in mp)
freq.Add(new int[] { entry.Key, entry.Value });
// Sort the list 'freq' on the basis of the
// 'FrequencyComparer' function
freq.Sort(new FrequencyComparer());
List<int> res = new List<int>();
// Extract and store the top k frequent elements
for (int i = 0; i < k; i++)
res.Add(freq[i][0]);
return res;
}
//Driver Code Starts
public static void Main() {
int[] arr = { 3, 1, 4, 4, 5, 2, 6, 1 };
int k = 2;
List<int> res = topKFreq(arr, k);
foreach (int val in res)
Console.Write(val + " ");
}
}
//Driver Code Ends
function compare(p1, p2) {
// Prioritise element's value in case
//their frequency was same
if (p1[1] === p2[1])
return p2[0] - p1[0];
// Sort on the basis of decreasing order
// of frequencies
return p2[1] - p1[1];
}
// Function to find k numbers with most occurrences
function topKFreq(arr, k) {
let n = arr.length;
let mp = {};
for (let i = 0; i < n; i++)
mp[arr[i]] = (mp[arr[i]] || 0) + 1;
// Store the elements of 'mp' in the array 'freq'
let freq = Object.entries(mp).map(([key, value]) => [parseInt(key), value]);
// Sort the array 'freq' on the basis of the
// 'compare' function
freq.sort(compare);
let res = [];
// Extract and store the top k frequent elements
for (let i = 0; i < k; i++)
res.push(freq[i][0]);
return res;
}
// Driver code
//Driver Code Starts
let arr = [3, 1, 4, 4, 5, 2, 6, 1];
let k = 2;
let res = topKFreq(arr, k);
console.log(res.join(" "));
//Driver Code Ends
Output
4 1
Time Complexity: O(n +d*log d), where n is the size of the array and d is the count of distinct elements in the array.
Auxiliary Space: O(d)
[Expected Approach 1] Using Hash map and Min Heap
The idea is to use a hashmap to store each element and its frequency. Then, use a priority queue (min-heap) to store pairs of frequency and element, so that the element with the smallest frequency is on top. Iterate through the hashmap and push each pair into the heap, and if the heap size exceeds k, remove the top element. After processing all elements, the heap will contain the k most frequent elements. Finally, extract these elements from the heap and store them in the result array.
#include <algorithm>
#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>
using namespace std;
vector<int> topKFreq(vector<int> &arr, int k) {
unordered_map<int, int> mp;
for (int val: arr)
mp[val]++;
// Min-heap to keep track of top k frequent elements
//{frequency, element}
priority_queue<pair<int, int>,
vector<pair<int, int>>, greater<pair<int, int>>> pq;
for (pair<int, int> entry : mp) {
// Push the current element and its frequency into heap
pq.push({entry.second, entry.first});
// If heap size exceeds k,
//remove the element with smallest frequency
if (pq.size() > k)
pq.pop();
}
vector<int> res(k);
// Extract elements from heap in descending frequency order
for (int i = k-1; i >= 0; i--) {
res[i] = pq.top().second;
pq.pop();
}
return res;
}
int main() {
vector<int> arr = {3, 1, 4, 4, 5, 2, 6, 1};
int k = 2;
vector<int> res = topKFreq(arr, k);
for (int i = 0; i < res.size(); i++)
cout << res[i] << " ";
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Collections;
class GFG {
static ArrayList<Integer> topKFreq(int[] arr, int k)
{
HashMap<Integer, Integer> mp = new HashMap<>();
for (int val : arr)
mp.put(val, mp.getOrDefault(val, 0) + 1);
// Min-heap to keep track of top k frequent elements
// {frequency, element}
PriorityQueue<int[]> pq = new PriorityQueue<>
((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
for (Map.Entry<Integer, Integer> entry : mp.entrySet()) {
// Push the current element and its frequency
// into heap
pq.add(new int[] { entry.getValue(), entry.getKey() });
// If heap size exceeds k,
// remove the element with smallest frequency
if (pq.size() > k)
pq.poll();
}
// Extract elements from heap in descending
// frequency order
ArrayList<Integer> res = new ArrayList<>();
while (!pq.isEmpty()) {
res.add(pq.poll()[1]);
}
return res;
}
public static void main(String[] args)
{
int[] arr = { 3, 1, 4, 4, 5, 2, 6, 1 };
int k = 2;
ArrayList<Integer> res = topKFreq(arr, k);
Collections.reverse(res);
for (int i = 0; i < res.size(); i++)
System.out.print(res.get(i) + " ");
}
}
import heapq
def topKFreq(arr, k):
# Dictionary to store frequency of each element
mp = {}
for val in arr:
mp[val] = mp.get(val, 0) + 1
# Min-heap to keep track of top k frequent elements
# Each element in heap: [frequency, element]
pq = []
for key, freq in mp.items():
# Push the current element and its frequency into heap
heapq.heappush(pq, [freq, key])
# If heap size exceeds k,
# remove the element with smallest frequency
if len(pq) > k:
heapq.heappop(pq)
res = []
# Extract elements from heap in descending frequency order
temp = [0] * len(pq)
index = len(pq) - 1
while pq:
temp[index] = heapq.heappop(pq)[1]
index -= 1
for val in temp:
res.append(val)
return res
if __name__ == "__main__":
arr = [3, 1, 4, 4, 5, 2, 6, 1]
k = 2
res = topKFreq(arr, k)
for val in res:
print(val, end=" ")
using System;
using System.Collections.Generic;
// Custom MinHeap class
class MinHeap {
private List<(int freq, int val)> heap = new List<(int, int)>();
private void Swap(int i, int j) {
var temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}
private void HeapifyUp(int index) {
while (index > 0) {
int parent = (index - 1) / 2;
if (Compare(heap[index], heap[parent]) < 0) {
Swap(index, parent);
index = parent;
} else break;
}
}
private void HeapifyDown(int index) {
int n = heap.Count;
while (true) {
int left = 2 * index + 1;
int right = 2 * index + 2;
int smallest = index;
if (left < n && Compare(heap[left], heap[smallest]) < 0)
smallest = left;
if (right < n && Compare(heap[right], heap[smallest]) < 0)
smallest = right;
if (smallest != index) {
Swap(index, smallest);
index = smallest;
} else break;
}
}
// Compare by frequency, then by value
private int Compare((int freq, int val) a, (int freq, int val) b) {
if (a.freq != b.freq) return a.freq - b.freq;
return a.val - b.val;
}
public void Add(int val, int freq) {
heap.Add((freq, val));
HeapifyUp(heap.Count - 1);
}
public (int freq, int val) Pop() {
var top = heap[0];
heap[0] = heap[heap.Count - 1];
heap.RemoveAt(heap.Count - 1);
if (heap.Count > 0) HeapifyDown(0);
return top;
}
public (int freq, int val) Peek() {
return heap[0];
}
public int Count() {
return heap.Count;
}
}
class GFG {
static List<int> topKFreq(int[] arr, int k) {
// Dictionary to store frequency of each element
Dictionary<int, int> mp = new Dictionary<int, int>();
foreach (int val in arr) {
if (mp.ContainsKey(val))
mp[val]++;
else
mp[val] = 1;
}
// Min-heap to keep track of top k frequent elements
// [frequency, element]
MinHeap pq = new MinHeap();
foreach (var entry in mp) {
// Push the current element
// and its frequency into heap
pq.Add(entry.Key, entry.Value);
// If heap size exceeds k, remove
// the element with smallest frequency
if (pq.Count() > k)
pq.Pop();
}
// Extract elements from heap
// in descending frequency order
List<int> res = new List<int>();
while (pq.Count() > 0)
res.Insert(0, pq.Pop().val);
return res;
}
static void Main() {
int[] arr = {3, 1, 4, 4, 5, 2, 6, 1};
int k = 2;
List<int> res = topKFreq(arr, k);
foreach (int val in res)
Console.Write(val + " ");
}
}
// Min-Heap class
class MinHeap {
constructor() {
this.heap = [];
}
push(item) {
this.heap.push(item);
this._heapifyUp();
}
pop() {
if (this.size() === 0) return null;
const top = this.heap[0];
const end = this.heap.pop();
if (this.size() > 0) {
this.heap[0] = end;
this._heapifyDown();
}
return top;
}
size() {
return this.heap.length;
}
_heapifyUp() {
let idx = this.heap.length - 1;
while (idx > 0) {
let parent = Math.floor((idx - 1) / 2);
// Compare frequency first, if equal compare element value
if (this._compare(this.heap[idx], this.heap[parent]) >= 0) break;
[this.heap[idx], this.heap[parent]] = [this.heap[parent], this.heap[idx]];
idx = parent;
}
}
_heapifyDown() {
let idx = 0;
const n = this.heap.length;
while (true) {
let left = 2 * idx + 1;
let right = 2 * idx + 2;
let smallest = idx;
if (left < n && this._compare(this.heap[left], this.heap[smallest]) < 0) smallest = left;
if (right < n && this._compare(this.heap[right], this.heap[smallest]) < 0) smallest = right;
if (smallest === idx) break;
[this.heap[idx], this.heap[smallest]] = [this.heap[smallest], this.heap[idx]];
idx = smallest;
}
}
top() {
return this.heap[0];
}
// Comparison: first by frequency, then by element value
_compare(a, b) {
if (a[0] !== b[0]) return a[0] - b[0];
return a[1] - b[1];
}
}
function topKFreq(arr, k) {
// Map to store frequency of each element
let mp = new Map();
for (let val of arr) {
mp.set(val, (mp.get(val) || 0) + 1);
}
// Min-heap to keep track of top k frequent elements
// [frequency, element]
let pq = new MinHeap();
for (let [key, freq] of mp.entries()) {
// Push the current element
// and its frequency into heap
pq.push([freq, key]);
// If heap size exceeds k, remove
// the element with smallest frequency
if (pq.size() > k)
pq.pop();
}
let res = [];
// Extract elements from heap
// in descending frequency order
let temp = [];
while (pq.size() > 0) temp.push(pq.pop());
for (let i = temp.length - 1; i >= 0; i--) res.push(temp[i][1]);
return res;
}
// Driver code
let arr = [3, 1, 4, 4, 5, 2, 6, 1];
let k = 2;
let res = topKFreq(arr, k);
console.log(...res);
Output
4 1
Time Complexity: O(n + k*log k ), where n is the size of array.
Auxiliary Space: O(d), where d is the count of distinct elements in the array.
[Expected Approach 2] Using Counting sort - O(n log n) Time and O(n) Space
The idea is to utilise more space to improve the time complexity, we store the elements based on their frequencies. We can use the frequency of each element as index of 2D array, where each index represents a list of elements of specific frequency. By doing this, we reduce the need for complex sorting operations. Instead, we can efficiently traverse the buckets from highest frequency to lowest and collect the top k most frequent elements.
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> topKFreq(vector<int>& arr, int k) {
// Count frequency of each element
unordered_map<int, int> freq;
for (int num : arr) {
freq[num]++;
}
//Find the maximum frequency
int maxFreq = 0;
for (pair<int,int> entry : freq) {
maxFreq = max(maxFreq, entry.second);
}
// Create buckets based on frequencies
// Each bucket index represents frequency
vector<vector<int>> buckets(maxFreq + 1);
for (pair<int,int> entry : freq) {
buckets[entry.second].push_back(entry.first);
}
// Collect top k frequent elements
vector<int> res;
for (int i = maxFreq; i >= 1; --i) {
sort(buckets[i].begin(), buckets[i].end(),
greater<int>());
for (int num : buckets[i]) {
res.push_back(num);
if (res.size() == k) {
return res;
}
}
}
return res;
}
int main() {
vector<int> arr = { 3, 1, 4, 4, 5, 2, 6, 1 };
int k = 2;
vector<int> res = topKFreq(arr, k);
for (int num : res)
cout << num << " ";
return 0;
}
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.Collections;
class GFG {
static ArrayList<Integer> topKFreq(int[] arr, int k) {
// Count frequency of each element
HashMap<Integer, Integer> freq = new HashMap<>();
for (int num : arr) {
freq.put(num, freq.getOrDefault(num, 0) + 1);
}
// Find the maximum frequency
int maxFreq = 0;
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
maxFreq = Math.max(maxFreq, entry.getValue());
}
// Create buckets based on frequencies
// Each bucket index represents frequency
ArrayList<ArrayList<Integer>> buckets = new ArrayList<>();
for (int i = 0; i <= maxFreq; i++) {
buckets.add(new ArrayList<>());
}
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
buckets.get(entry.getValue()).add(entry.getKey());
}
// Collect top k frequent elements
ArrayList<Integer> res = new ArrayList<>();
for (int i = maxFreq; i >= 1; --i) {
Collections.sort(buckets.get(i), Collections.reverseOrder());
for (int num : buckets.get(i)) {
res.add(num);
if (res.size() == k) {
return res;
}
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {3, 1, 4, 4, 5, 2, 6, 1};
int k = 2;
ArrayList<Integer> res = topKFreq(arr, k);
for (int num : res)
System.out.print(num + " ");
}
}
def topKFreq(arr, k):
# Count frequency of each element
freq = {}
for num in arr:
freq[num] = freq.get(num, 0) + 1
# Find the maximum frequency
maxFreq = max(freq.values())
# Create buckets based on frequencies
# Each bucket index represents frequency
buckets = [[] for _ in range(maxFreq + 1)]
for num, count in freq.items():
buckets[count].append(num)
# Collect top k frequent elements
res = []
for i in range(maxFreq, 0, -1):
buckets[i].sort(reverse=True)
for num in buckets[i]:
res.append(num)
if len(res) == k:
return res
return res
if __name__ == "__main__":
arr = [3, 1, 4, 4, 5, 2, 6, 1]
k = 2
res = topKFreq(arr, k)
print(" ".join(map(str, res)))
using System;
using System.Collections.Generic;
using System.Linq;
class GFG {
static List<int> topKFreq(int[] arr, int k) {
// Count frequency of each element
Dictionary<int, int> freq = new Dictionary<int, int>();
foreach (int num in arr) {
if (!freq.ContainsKey(num))
freq[num] = 0;
freq[num]++;
}
// Find the maximum frequency
int maxFreq = freq.Values.Max();
// Create buckets based on frequencies
// Each bucket index represents frequency
List<List<int>> buckets = new List<List<int>>();
for (int i = 0; i <= maxFreq; i++)
buckets.Add(new List<int>());
foreach (var entry in freq)
buckets[entry.Value].Add(entry.Key);
// Collect top k frequent elements
List<int> res = new List<int>();
for (int i = maxFreq; i >= 1; --i) {
buckets[i].Sort((a, b) => b.CompareTo(a));
foreach (int num in buckets[i]) {
res.Add(num);
if (res.Count == k)
return res;
}
}
return res;
}
public static void Main() {
int[] arr = {3, 1, 4, 4, 5, 2, 6, 1};
int k = 2;
List<int> res = topKFreq(arr, k);
foreach (int num in res)
Console.Write(num + " ");
}
}
function topKFreq(arr, k) {
// Count frequency of each element
let freq = new Map();
for (let num of arr) {
freq.set(num, (freq.get(num) || 0) + 1);
}
// Find the maximum frequency
let maxFreq = Math.max(...freq.values());
// Create buckets based on frequencies
// Each bucket index represents frequency
let buckets = Array.from({ length: maxFreq + 1 }, () => []);
for (let [num, count] of freq.entries()) {
buckets[count].push(num);
}
// Collect top k frequent elements
let res = [];
for (let i = maxFreq; i >= 1; --i) {
buckets[i].sort((a, b) => b - a);
for (let num of buckets[i]) {
res.push(num);
if (res.length === k) {
return res;
}
}
}
return res;
}
// Driver code
let arr = [3, 1, 4, 4, 5, 2, 6, 1];
let k = 2;
let res = topKFreq(arr, k);
console.log(res.join(" "));
Output
4 1
[Alternate Approach] Using Quick Select
The idea is to use QuickSelect to find the top k frequent elements by partitioning the array based on element frequency. We pick a pivot and place all elements with higher frequency to its left and lower frequency to its right, putting the pivot in its correct position. We then recursively focus only on the part that can contain the k-th most frequent element.
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
// Partition function for quickselect
int partition(int left, int right, int pivotIdx,
vector<int> &distinct, unordered_map<int, int> &mp) {
// Frequency of pivot element
int pivotFreq = mp[distinct[pivotIdx]];
// Pivot element value
int pivotVal = distinct[pivotIdx];
swap(distinct[pivotIdx], distinct[right]);
int j = left;
for (int i = left; i < right; i++) {
// Place elements with smaller frequency OR smaller value first
// So top-k (highest freq, largest value) end up at the end
if (mp[distinct[i]] < pivotFreq ||
(mp[distinct[i]] == pivotFreq && distinct[i] < pivotVal)) {
swap(distinct[i], distinct[j]);
j++;
}
}
swap(distinct[j], distinct[right]);
return j;
}
// Quickselect function to partially sort the array
void quickselect(int left, int right, int k,
vector<int> &distinct, unordered_map<int, int> &mp) {
if (left >= right) return;
int pivotIdx = left + rand() % (right - left + 1);
pivotIdx = partition(left, right, pivotIdx, distinct, mp);
if (pivotIdx == k) return;
else if (pivotIdx > k)
quickselect(left, pivotIdx - 1, k, distinct, mp);
else
quickselect(pivotIdx + 1, right, k, distinct, mp);
}
// Function to find top k frequent elements
vector<int> topKFreq(vector<int>& arr, int k) {
vector<int> distinct;
unordered_map<int, int> mp;
// Count frequency of each element
for (int val : arr) mp[val]++;
// Store unique elements in distinct array
for (auto &p : mp) distinct.push_back(p.first);
int n = distinct.size();
// Quickselect to move top k frequent elements to the end
quickselect(0, n - 1, n - k, distinct, mp);
// Sort top k elements by frequency descending, then value descending
sort(distinct.begin() + n - k, distinct.end(), [&](int a, int b){
if(mp[a] != mp[b]) return mp[a] > mp[b];
return a > b;
});
// Collect top k frequent elements
vector<int> res;
for (int i = n - k; i < n; i++) res.push_back(distinct[i]);
return res;
}
int main() {
vector<int> arr{ 3, 1, 4, 4, 5, 2, 6, 1 };
int k = 2;
vector<int> res = topKFreq(arr, k);
for (int val: res)
cout << val << " ";
return 0;
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Random;
import java.util.Arrays;
import java.util.Collections;
class GFG {
// Partition function for quickselect
int partition(int left, int right, int pivotIdx,
Integer[] distinct, Map<Integer, Integer> mp) {
// Frequency of pivot element
int pivotFreq = mp.get(distinct[pivotIdx]);
// Pivot element value
int pivotVal = distinct[pivotIdx];
int temp = distinct[pivotIdx];
distinct[pivotIdx] = distinct[right];
distinct[right] = temp;
int j = left;
for (int i = left; i < right; i++) {
// Place elements with smaller frequency OR smaller value first
// So top-k (highest freq, largest value) end up at the end
if (mp.get(distinct[i]) < pivotFreq ||
(mp.get(distinct[i]) == pivotFreq && distinct[i] < pivotVal)) {
int t = distinct[i];
distinct[i] = distinct[j];
distinct[j] = t;
j++;
}
}
temp = distinct[j];
distinct[j] = distinct[right];
distinct[right] = temp;
return j;
}
// Quickselect function to partially sort the array
void quickselect(int left, int right, int k,
Integer[] distinct, Map<Integer, Integer> mp) {
if (left >= right) return;
int pivotIdx = left + new Random().nextInt(right - left + 1);
pivotIdx = partition(left, right, pivotIdx, distinct, mp);
if (pivotIdx == k) return;
else if (pivotIdx > k)
quickselect(left, pivotIdx - 1, k, distinct, mp);
else
quickselect(pivotIdx + 1, right, k, distinct, mp);
}
// Function to find top k frequent elements
ArrayList<Integer> topKFreq(int[] arr, int k) {
Set<Integer> set = new HashSet<>();
Map<Integer, Integer> mp = new HashMap<>();
// Count frequency of each element
for (int val : arr) {
mp.put(val, mp.getOrDefault(val, 0) + 1);
set.add(val);
}
// Convert set to array
Integer[] distinct = set.toArray(new Integer[0]);
int n = distinct.length;
// Quickselect to move top k frequent elements to the end
quickselect(0, n - 1, n - k, distinct, mp);
// Sort top k elements by frequency descending, then value descending
Arrays.sort(distinct, n - k, n, (a, b) -> {
if (!mp.get(a).equals(mp.get(b))) return mp.get(b) - mp.get(a);
return b - a;
});
// Collect top k frequent elements
ArrayList<Integer> res = new ArrayList<>();
for (int i = n - k; i < n; i++) res.add(distinct[i]);
return res;
}
public static void main(String[] args) {
GFG sol = new GFG();
int[] arr = {3, 1, 4, 4, 5, 2, 6, 1};
int k = 2;
ArrayList<Integer> res = sol.topKFreq(arr, k);
for (int val : res)
System.out.print(val + " ");
}
}
import random
# Partition function for quickselect
def partition(left, right, pivotIdx, distinct, freq_map):
pivotFreq = freq_map[distinct[pivotIdx]]
pivotVal = distinct[pivotIdx]
distinct[pivotIdx], distinct[right] = distinct[right], distinct[pivotIdx]
j = left
for i in range(left, right):
# Place elements with smaller frequency OR smaller value first
# So top-k (highest freq, largest value) end up at the end
if freq_map[distinct[i]] < pivotFreq or (freq_map[distinct[i]] == pivotFreq and distinct[i] < pivotVal):
distinct[i], distinct[j] = distinct[j], distinct[i]
j += 1
distinct[j], distinct[right] = distinct[right], distinct[j]
return j
# Quickselect function to partially sort the array
def quickselect(left, right, k, distinct, freq_map):
if left >= right:
return
pivotIdx = left + random.randint(0, right - left)
pivotIdx = partition(left, right, pivotIdx, distinct, freq_map)
if pivotIdx == k:
return
elif pivotIdx > k:
quickselect(left, pivotIdx - 1, k, distinct, freq_map)
else:
quickselect(pivotIdx + 1, right, k, distinct, freq_map)
# Function to find top k frequent elements
def topKFreq(arr, k):
freq_map = {}
distinct_set = set()
# Count frequency of each element
for val in arr:
freq_map[val] = freq_map.get(val, 0) + 1
distinct_set.add(val)
distinct = list(distinct_set)
n = len(distinct)
# Quickselect to move top k frequent elements to the end
quickselect(0, n - 1, n - k, distinct, freq_map)
# Sort top k elements by frequency descending, then value descending
top_k = distinct[n - k:]
top_k.sort(key=lambda x: (freq_map[x], x), reverse=True)
return top_k
if __name__ == "__main__":
arr = [3, 1, 4, 4, 5, 2, 6, 1]
k = 2
res = topKFreq(arr, k)
print(" ".join(str(x) for x in res))
using System;
using System.Collections.Generic;
class GFG {
// Partition function for quickselect
int partition(int left, int right, int pivotIdx,
int[] distinct, Dictionary<int, int> freqMap) {
int pivotFreq = freqMap[distinct[pivotIdx]];
int pivotVal = distinct[pivotIdx];
// Swap pivot with right
int temp = distinct[pivotIdx];
distinct[pivotIdx] = distinct[right];
distinct[right] = temp;
int j = left;
for (int i = left; i < right; i++)
{
// Place elements with smaller freq OR smaller value first
// So top-k (highest freq, largest value) end up at the end
if (freqMap[distinct[i]] < pivotFreq ||
(freqMap[distinct[i]] == pivotFreq && distinct[i] < pivotVal)) {
temp = distinct[i];
distinct[i] = distinct[j];
distinct[j] = temp;
j++;
}
}
temp = distinct[j];
distinct[j] = distinct[right];
distinct[right] = temp;
return j;
}
// Quickselect function to partially sort the array
void quickselect(int left, int right, int k, int[] distinct,
Dictionary<int, int> freqMap) {
if (left >= right) return;
Random rand = new Random();
int pivotIdx = left + rand.Next(right - left + 1);
pivotIdx = partition(left, right, pivotIdx, distinct, freqMap);
if (pivotIdx == k) return;
else if (pivotIdx > k)
quickselect(left, pivotIdx - 1, k, distinct, freqMap);
else
quickselect(pivotIdx + 1, right, k, distinct, freqMap);
}
// Function to find top k frequent elements
public List<int> topKFreq(int[] arr, int k) {
Dictionary<int, int> freqMap = new Dictionary<int, int>();
HashSet<int> distinctSet = new HashSet<int>();
// Count frequency of each element
foreach (int val in arr)
{
if (!freqMap.ContainsKey(val)) freqMap[val] = 0;
freqMap[val]++;
distinctSet.Add(val);
}
int n = distinctSet.Count;
int[] distinct = new int[n];
distinctSet.CopyTo(distinct);
// Quickselect to move top k frequent elements to the end
quickselect(0, n - 1, n - k, distinct, freqMap);
// Sort top k elements by frequency descending, then value descending
Array.Sort(distinct, n - k, k, Comparer<int>.Create((a, b) =>
{
if (freqMap[a] != freqMap[b]) return freqMap[b] - freqMap[a];
return b - a;
}));
// Collect top k frequent elements
List<int> res = new List<int>();
for (int i = n - k; i < n; i++)
res.Add(distinct[i]);
return res;
}
static void Main()
{
int[] arr = { 3, 1, 4, 4, 5, 2, 6, 1 };
int k = 2;
GFG obj = new GFG();
List<int> res = obj.topKFreq(arr, k);
Console.WriteLine(string.Join(" ", res));
}
}
function partition(left, right, pivotIdx, distinct, freqMap) {
let pivotFreq = freqMap.get(distinct[pivotIdx]);
let pivotVal = distinct[pivotIdx];
// Swap pivot with right
[distinct[pivotIdx], distinct[right]] = [distinct[right], distinct[pivotIdx]];
let j = left;
for (let i = left; i < right; i++) {
// Place elements with smaller freq OR smaller value first
// So top-k (highest freq, largest value) end up at the end
if (freqMap.get(distinct[i]) < pivotFreq ||
(freqMap.get(distinct[i]) === pivotFreq && distinct[i] < pivotVal)) {
[distinct[i], distinct[j]] = [distinct[j], distinct[i]];
j++;
}
}
[distinct[j], distinct[right]] = [distinct[right], distinct[j]];
return j;
}
function quickselect(left, right, k, distinct, freqMap) {
if (left >= right) return;
let pivotIdx = left + Math.floor(Math.random() * (right - left + 1));
pivotIdx = partition(left, right, pivotIdx, distinct, freqMap);
if (pivotIdx === k) return;
else if (pivotIdx > k) quickselect(left, pivotIdx - 1, k, distinct, freqMap);
else quickselect(pivotIdx + 1, right, k, distinct, freqMap);
}
function topKFreq(arr, k) {
let freqMap = new Map();
let distinctSet = new Set();
// Count frequency of each element
for (let val of arr) {
freqMap.set(val, (freqMap.get(val) || 0) + 1);
distinctSet.add(val);
}
let distinct = Array.from(distinctSet);
let n = distinct.length;
// Quickselect to move top k frequent elements to the end
quickselect(0, n - 1, n - k, distinct, freqMap);
// Sort top k elements by frequency descending, then value descending
let topK = distinct.slice(n - k);
topK.sort((a, b) => {
if (freqMap.get(a) !== freqMap.get(b)) return freqMap.get(b) - freqMap.get(a);
return b - a;
});
return topK;
}
// Driver Code
let arr = [3, 1, 4, 4, 5, 2, 6, 1];
let k = 2;
let res = topKFreq(arr, k);
console.log(res.join(" "));
Output
4 1
Time complexity: O(n + d^2), the QuickSelect algorithm takes O(d log d) time on average and works faster than other O(d log d) algorithms in practice.
Auxiliary Space: O(n)