Sort elements by frequency | Set 1 - GeeksforGeeks

20 Jan, 2022
Print the elements of an array in the decreasing frequency if 2 numbers have same frequency then print the one which came first. 
Examples:  
Input:  arr[] = {2, 5, 2, 8, 5, 6, 8, 8}
Output: arr[] = {8, 8, 8, 2, 2, 5, 5, 6}

Input: arr[] = {2, 5, 2, 6, -1, 9999999, 5, 8, 8, 8}
Output: arr[] = {8, 8, 8, 2, 2, 5, 5, 6, -1, 9999999}
METHOD 1 (Use Sorting) 
Use a sorting algorithm to sort the elements O(nlogn)
Scan the sorted array and construct a 2D array of element and count O(n).
Sort the 2D array according to count O(nlogn).
Example:  
  Input 2 5 2 8 5 6 8 8

  After sorting we get
  2 2 5 5 6 8 8 8

  Now construct the 2D array as
  2, 2
  5, 2
  6, 1
  8, 3

  Sort by count
  8, 3
  2, 2
  5, 2
  6, 1
How to maintain the order of elements if the frequency is the same?
Chapters
descriptions off, selected
captions settings, opens captions settings dialog
captions off, selected
English
This is a modal window.
Beginning of dialog window. Escape will cancel and close the window.
End of dialog window.
The above approach doesn’t make sure order of elements if the frequency is the same. To handle this, we should use indexes in step 3, if two counts are same then we should first process(or print) the element with a lower index. In step 1, we should store the indexes instead of elements. 
  Input   2  5  2  8  5  6  8  8

  After sorting we get
  Element 2 2 5 5 6 8 8 8
  Index   0 2 1 4 5 3 6 7

  Now construct the 2D array as
  Index, Count
  0,      2
  1,      2
  5,      1
  3,      3

  Sort by count (consider indexes in case of tie)
  3, 3
  0, 2
  1, 2
  5, 1
  
  Print the elements using indexes in the above 2D array.
Below is the implementation of above approach –
CPP
// Sort elements by frequency. If two elements have same// count, then put the elements that appears first#include <bits/stdc++.h>using namespace std; // Used for sortingstruct ele {    int count, index, val;}; // Used for sorting by valuebool mycomp(struct ele a, struct ele b){    return (a.val < b.val);} // Used for sorting by frequency. And if frequency is same,// then by appearancebool mycomp2(struct ele a, struct ele b){    if (a.count != b.count)        return (a.count < b.count);    else        return a.index > b.index;} void sortByFrequency(int arr[], int n){    struct ele element[n];    for (int i = 0; i < n; i++) {         // Fill Indexes        element[i].index = i;         // Initialize counts as 0        element[i].count = 0;         // Fill values in structure        // elements        element[i].val = arr[i];    }     /* Sort the structure elements according to value,       we used stable sort so relative order is maintained.     */    stable_sort(element, element + n, mycomp);     /* initialize count of first element as 1 */    element[0].count = 1;     /* Count occurrences of remaining elements */    for (int i = 1; i < n; i++) {         if (element[i].val == element[i - 1].val) {            element[i].count += element[i - 1].count + 1;             /* Set count of previous element as -1, we are               doing this because we'll again sort on the               basis of counts (if counts are equal than on               the basis of index)*/            element[i - 1].count = -1;             /* Retain the first index (Remember first index               is always present in the first duplicate we               used stable sort. */            element[i].index = element[i - 1].index;        }         /* Else If previous element is not equal to current          so set the count to 1 */        else            element[i].count = 1;    }     /* Now we have counts and first index for each element       so now sort on the basis of count and in case of tie       use index to sort.*/    stable_sort(element, element + n, mycomp2);    for (int i = n - 1, index = 0; i >= 0; i--)        if (element[i].count != -1)            for (int j = 0; j < element[i].count; j++)                arr[index++] = element[i].val;} // Driver programint main(){    int arr[] = { 2, 5, 2, 6, -1, 9999999, 5, 8, 8, 8 };    int n = sizeof(arr) / sizeof(arr[0]);     sortByFrequency(arr, n);     for (int i = 0; i < n; i++)        cout << arr[i] << " ";    return 0;}
Output: 
8 8 8 2 2 5 5 6 -1 9999999
Thanks to Gaurav Ahirwar for providing above implementation.
METHOD 2 (Use Hashing and Sorting) Using a hashing mechanism, we can store the elements (also first index) and their counts in a hash. Finally, sort the hash elements according to their counts.Below is the implementation of above approach – 
CPP
Java
Python3
Javascript
// CPP program for above approach#include <bits/stdc++.h>using namespace std; // Compare functionbool fcompare(pair<int, pair<int, int> > p,              pair<int, pair<int, int> > p1){    if (p.second.second != p1.second.second)        return (p.second.second > p1.second.second);    else        return (p.second.first < p1.second.first);}void sortByFrequency(int arr[], int n){    unordered_map<int, pair<int, int> > hash; // hash map    for (int i = 0; i < n; i++) {        if (hash.find(arr[i]) != hash.end())            hash[arr[i]].second++;        else            hash[arr[i]] = make_pair(i, 1);    } // store the count of all the elements in the hashmap     // Iterator to Traverse the Hashmap    auto it = hash.begin();     // Vector to store the Final Sortted order    vector<pair<int, pair<int, int> > > b;    for (it; it != hash.end(); ++it)        b.push_back(make_pair(it->first, it->second));     sort(b.begin(), b.end(), fcompare);     // Printing the Sorted sequence    for (int i = 0; i < b.size(); i++) {        int count = b[i].second.second;        while (count--)            cout << b[i].first << " ";    }} // Driver Functionint main(){    int arr[] = { 2, 5, 2, 6, -1, 9999999, 5, 8, 8, 8 };    int n = sizeof(arr) / sizeof(arr[0]);     sortByFrequency(arr, n);     return 0;}
/*package whatever //do not write package name here */import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.List;class GFG {     static Integer[] arr = { 2, 5, 2, 8, 5, 6, 8, 8 };     // Driver Code    public static void main(String[] args)    {        List<Integer> list = Arrays.asList(arr);        sortBasedOnFrequencyAndValue(list);    }       // Compare Function    public static void    sortBasedOnFrequencyAndValue(List<Integer> list)    {        int n = arr.length;        final HashMap<Integer, Integer> mapCount            = new HashMap<Integer, Integer>();        final HashMap<Integer, Integer> mapIndex            = new HashMap<Integer, Integer>();        for (int i = 0; i < n; i++) {            if (mapCount.containsKey(arr[i])) {                mapCount.put(arr[i],                             mapCount.get(arr[i]) + 1);            }            else {                mapCount.put(arr[i],1); // Map to capture Count of elements                mapIndex.put(arr[i],i); // Map to capture 1st occurrence of elements            }        }         Collections.sort(list, new Comparator<Integer>() {            public int compare(Integer n1, Integer n2)            {                int freq1 = mapCount.get(n1);                int freq2 = mapCount.get(n2);                if (freq1 != freq2) {                    return freq2 - freq1;                }                else {                    return mapIndex.get(n1)                        - mapIndex.get(                            n2); // Elements with Lesser                                 // Index gets Higher                                 // Priority                }            }        });        System.out.println(list);    }}
# Python program for above approach from collections import defaultdict # Sort by Frequency  def sortByFreq(arr, n):    # arr -> Array to be sorted    # n   -> Length of Array     # d is a hashmap(referred as dictionary in python)    d = defaultdict(lambda: 0)    for i in range(n):        d[arr[i]] += 1     # Sorting the array 'arr' where key    # is the function based on which    # the array is sorted    # While sorting we want to give    # first priority to Frequency    # Then to value of item    arr.sort(key=lambda x: (-d[x], x))     return (arr)  # Driver Functionif __name__ == "__main__":    arr = [2, 5, 2, 6, -1, 9999999, 5, 8, 8, 8]    n = len(arr)    solution = sortByFreq(arr, n)    print(*solution)
<script> let arr=[2, 5, 2, 6, -1, 9999999, 5, 8, 8, 8]; // Compare Functionfunction sortBasedOnFrequencyAndValue(list){    let n = arr.length;        let  mapCount            = new Map();        let  mapIndex            = new Map();        for (let i = 0; i < n; i++) {            if (mapCount.has(arr[i])) {                mapCount.set(arr[i],                             mapCount.get(arr[i]) + 1);            }            else {                mapCount.set(arr[i],1); // Map to capture Count of elements                mapIndex.set(arr[i],i); // Map to capture 1st occurrence of elements            }        }          list.sort(function(n1,n2){                             let freq1 = mapCount.get(n1);                let freq2 = mapCount.get(n2);                if (freq1 != freq2) {                    return freq2 - freq1;                }                else {                    return mapIndex.get(n1)                        - mapIndex.get(                            n2); // Elements with Lesser                                 // Index gets Higher                                 // Priority                }                     });        document.write(list.join(" "));} // Driver CodesortBasedOnFrequencyAndValue(arr); // This code is contributed by patel2127</script>
Output: 
8 8 8 2 2 5 5 6 -1 9999999
This can also be solved by Using two maps, one for array element as an index and after this second map whose keys are frequency and value are array elements.
METHOD 3(Use BST and Sorting) 
Insert elements in BST one by one and if an element is already present then increment the count of the node. Node of the Binary Search Tree (used in this approach) will be as follows.
C
Java
C#
struct tree {    int element;    int first_index /*To handle ties in counts*/        int count;} BST;</div>
static class tree {    int element;    int first_index; /*To handle ties in counts*/    int count;}tree BST = new tree(); // This code is contributed by gauravrajput1
public class tree {    public int element;    public int first_index; /* To handle ties in counts */    public int count;}tree BST = new tree(); // This code is contributed by gauravrajput1
Store the first indexes and corresponding counts of BST in a 2D array.
Sort the 2D array according to counts (and use indexes in case of tie).
Time Complexity: O(nlogn) if a Self Balancing Binary Search Tree is used. This is implemented in Set 2. https://youtu.be/NBXf9vCksuM Set 2: Sort elements by frequency | Set 2Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above 
praveenjain6407
anumoluhemanth
ahmadzaidju
Koushik222
ayushagrawal99
shivagarg
prithicogni89
patel2127
nisanth2590
GauravRajput1
Amazon
Oracle
Zoho
Zycus
Arrays
Sorting
Zoho
Amazon
Oracle
Zycus
Arrays
Sorting
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Introduction to Arrays
Multidimensional Arrays in Java
Linked List vs Array
Python | Using 2D arrays/lists the right way
Search an element in a sorted and rotated array