# Top K Frequent Elements

Difficulty Level Medium
Array Hash Hashing Heap

## Problem Statement

In top K frequent elements we have given an array nums[], find the k most frequently occurring elements.

## Examples

```nums[] = {1, 1, 1, 2, 2, 3}
k = 2```
`1 2`

```nums[] = {1}
k = 1```
`1`

## Naive Approach for Top K Frequent Elements

1. Build a map of element and frequency by traversing in the given array.
2. Sort the entries of the map according to the decreasing order of frequency.
3. The first k elements of the sorted map contribute to the answer.

Example

nums[] = {1, 1, 2, 3, 3, 3, 4} and k = 2

Build map of elements and frequency
map = {(1, 2), (2, 1), (3, 3), (4, 1)}

Sort the map in decreasing order of frequency
sorted map = {(3, 3), (1, 2), (2, 1), (4, 1)}

First k entries contributes to the answer
ans = 3 1

### Code

#### Java Code for Top K Frequent Elements

```import java.util.*;

class TopKFrequentElements {
private static void printKFrequent(int[] nums, int k) {
// Length of nums array
int n = nums.length;

// Build the map from nums array
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < n; i++) {
if (map.containsKey(nums[i])) {
map.put(nums[i], map.get(nums[i]) + 1);
} else {
map.put(nums[i], 1);
}
}

// Sort the map, according to decreasing order of frequency and store in a set
TreeSet<Element> set = new TreeSet<>(new Comparator<Element>() {
@Override
public int compare(Element o1, Element o2) {
return Integer.compare(o2.freq, o1.freq);
}
});

for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
Element curr = new Element(entry.getKey(), entry.getValue());
}

// First k elements of the sorted map contributes to the answer
int index = 0;
for (Element element : set) {
System.out.print(element.value + " ");
index++;
if (index == k)
break;
}
System.out.println();
}

public static void main(String[] args) {
// Example 1
int nums[] = new int[]{1, 1, 1, 2, 2, 3};
int k = 2;

printKFrequent(nums, k);

// Example 2
nums = new int[]{1};
k = 1;

printKFrequent(nums, k);
}

// class representing a element and value pair
static class Element {
int value;
int freq;

public Element(int value, int freq) {
this.value = value;
this.freq = freq;
}
}
}```

#### C++ Code for Top K Frequent Elements

```#include <bits/stdc++.h>
using namespace std;

// structure representing a element and value pair
struct Element {
int value;
int freq;

Element(int v, int f) {
value = v;
freq = f;
}
};

// Comparator to sort elements according to decreasing order of frequency
struct ElemetComp {
bool operator()(const Element &e1, const Element & e2) {
return (e2.freq < e1.freq);
}
};

void printKFrequent(int *nums, int k, int n) {
// Build the map from nums array
unordered_map<int, int> map;
for (int i = 0; i < n; i++) {
if (map.find(nums[i]) == map.end()) {
map.insert(make_pair(nums[i], 1));
} else {
map[nums[i]] = map.find(nums[i])->second + 1;
}
}

// Sort the map, according to decreasing order of frequency and store in a set
set<Element, ElemetComp> set;
unordered_map<int, int>:: iterator itr;
for (itr = map.begin(); itr != map.end(); itr++) {
Element curr(itr->first, itr->second);
set.insert(curr);
}

// First k elements of the sorted map contributes to the answer
int index = 0;
for (auto it = set.begin(); it != set.end(); it++) {
cout<<it->value<<" ";
index++;
if (index == k)
break;
}
cout<<endl;
}

int main() {
// Example 1
int nums[] = {1, 1, 1, 2, 2, 3};
int k = 2;

printKFrequent(nums, k, 6);

// Example 2
int nums2 = {1};
k = 1;

printKFrequent(nums, k, 1);

return 0;
}```

### Complexity Analysis

#### Time Complexity

O(N * log(N)), cause we have used a map. And map takes log N time for insertion of elements.

#### Space Complexity

O(N),Â here we are inserting the elements into the map, which is responsible for this space. Since we inserted N elements, the space complexity is also O(N). Here, N denoted the number of distinct elements. In the worst-case, all numbers might be distinct.

## Optimal Approach for Top K Frequent Elements

A better approach is to make a max heap of the element and frequency, according to frequency, removing the top of heap k times gives the answer.

1. Build a map of element and frequency by traversing in the given array.
2. Build a max heap according to frequency from the map.
3. Remove the top of heap k times and this is the answer.

### Code for Top K Frequent Elements

#### Java Code

```import java.util.*;

class TopKFrequentElements {
private static void printKFrequent(int[] nums, int k) {
// Length of nums array
int n = nums.length;

// Build the map from nums array
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < n; i++) {
if (map.containsKey(nums[i])) {
map.put(nums[i], map.get(nums[i]) + 1);
} else {
map.put(nums[i], 1);
}
}

// Construct a max heap of element and frequency according to frequency
PriorityQueue<Element> heap = new PriorityQueue<>(new Comparator<Element>() {
@Override
public int compare(Element o1, Element o2) {
return Integer.compare(o2.freq, o1.freq);
}
});

// Build heap
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
}

// First k elements of heap contributes to the answer
for (int i = 0; i < k; i++) {
System.out.print(heap.poll().value + " ");
}
System.out.println();
}

public static void main(String[] args) {
// Example 1
int nums[] = new int[]{1, 1, 1, 2, 2, 3};
int k = 2;

printKFrequent(nums, k);

// Example 2
nums = new int[]{1};
k = 1;

printKFrequent(nums, k);
}

// class representing a element and value pair
static class Element {
int value;
int freq;

public Element(int value, int freq) {
this.value = value;
this.freq = freq;
}
}
}```

#### C++ Code

```#include <bits/stdc++.h>
using namespace std;

// structure representing a element and value pair
struct Element {
int value;
int freq;

Element(int v, int f) {
value = v;
freq = f;
}
};

// Comparator to sort elements according to decreasing order of frequency
struct ElementComp {
bool operator()(const Element &e1, const Element & e2) {
return (e1.freq < e2.freq);
}
};

void printKFrequent(int *nums, int k, int n) {
// Build the map from nums array
unordered_map<int, int> map;
for (int i = 0; i < n; i++) {
if (map.find(nums[i]) == map.end()) {
map.insert(make_pair(nums[i], 1));
} else {
map[nums[i]] = map.find(nums[i])->second + 1;
}
}

// Construct a max heap of element and frequency according to frequency
priority_queue<Element, vector<Element>, ElementComp> heap;
for (auto itr = map.begin(); itr != map.end(); itr++) {
Element element(itr->first, itr->second);
heap.push(element);
}

// First k elements of heap contributes to the answer
for (int i = 0; i < k; i++) {
Element curr = heap.top();
heap.pop();
cout<<curr.value<<" ";
}
cout<<endl;
}

int main() {
// Example 1
int nums[] = {1, 1, 1, 2, 2, 3};
int k = 2;

printKFrequent(nums, k, 6);

// Example 2
int nums2 = {1};
k = 1;

printKFrequent(nums, k, 1);

return 0;
}```

### Complexity Analysis

#### Time Complexity

O(k log N + N), here N is the number of elements. Because in the worst-case all of the numbers present in the input might be distinct.
O(log N) factor comes because of the time to insert an element into the max heap or priority queue.

#### Space Complexity

O(N), because we are storing N elements ion worst-case. The space complexity is linear.

References

Wait !!! You can Crack Technical Interviews of Companies like Amazon, Google, LinkedIn, Facebook, PayPal, Flipkart, etc

Anisha was able to crack Amazon after practicing questions from TutorialCup