Top K Frequent in an Array (original) (raw)

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.

C++ `

//Driver Code Starts #include #include #include #include

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 topKFreq(vector&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

Java

//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 res = topKFreq(arr, k);

    for (int val : res)
        System.out.print(val + " ");
}

}

//Driver Code Ends

Python

#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

C#

//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 res = topKFreq(arr, k);

    foreach (int val in res)
        Console.Write(val + " ");
}

}

//Driver Code Ends

JavaScript

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

`

**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.

C++ `

#include #include #include #include #include using namespace std;

vector topKFreq(vector &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] << " ";

}

Java

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) + " ");
}

}

Python

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=" ")

C#

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 + " ");
}

}

JavaScript

// 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);

`

**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.

C++ `

#include #include #include #include using namespace std;

vector topKFreq(vector& 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 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;

}

Java

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 + " ");
}

}

Python

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)))

C#

using System; using System.Collections.Generic; using System.Linq;

class GFG { static List 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 + " ");
}

}

JavaScript

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(" "));

`

[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.

C++ `

#include #include #include #include

using namespace std;

// Partition function for quickselect int partition(int left, int right, int pivotIdx, vector &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 &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 topKFreq(vector& arr, int k) { vector 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 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;

}

Java

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 + " ");
}

}

Python

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))

C#

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));
}

}

JavaScript

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(" "));

`

**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)