📌  相关文章
📜  按频率对元素进行排序|套装1

📅  最后修改于: 2021-04-29 06:44:25             🧑  作者: Mango

如果2个数字具有相同的频率,则以递减的频率打印数组的元素,然后打印第一个出现的频率。

例子:

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}

方法1(使用排序)

  • 使用排序算法对元素O(nlogn)进行排序
  • 扫描排序的数组并构造一个2D元素数组,并计数O(n)。
  • 根据计数O(nlogn)对2D数组排序。

例子:

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

如果频率相同,如何保持元素的顺序?

如果频率相同,则上述方法无法确定元素的顺序。要处理此问题,我们应该在第3步中使用索引,如果两个计数相同,那么我们应该首先处理(或打印)索引较低的元素。在第1步中,我们应该存储索引而不是元素。

Input 5  2  2  8  5  6  8  8

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

  Now construct the 2D array as
  Index, Count
  1,      2
  0,      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.

以下是上述方法的实现–

CPP
// Sort elements by frequency. If two elements have same
// count, then put the elements that appears first
#include 
using namespace std;
 
// Used for sorting
struct ele {
    int count, index, val;
};
 
// Used for sorting by value
bool mycomp(struct ele a, struct ele b)
{
    return (a.val < b.val);
}
 
// Used for sorting by frequency. And if frequency is same,
// then by appearance
bool 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 program
int 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;
}


CPP
// CPP program for above approach
#include 
using namespace std;
 
// Compare function
bool fcompare(pair > p,
              pair > 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 > 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 > > 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 Function
int 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;
}


Python3
# 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 Function
if __name__ == "__main__":
    arr = [2, 5, 2, 6, -1, 9999999, 5, 8, 8, 8]
    n = len(arr)
    solution = sortByFreq(arr, n)
    print(*solution)


C
struct tree {
    int element;
    int first_index /*To handle ties in counts*/
        int count;
} BST;


输出

8 8 8 2 2 5 5 6 -1 9999999

感谢Gaurav Ahirwar提供了上述实现。

方法2(使用散列和排序)
使用哈希机制,我们可以将元素(也是第一个索引)及其计数存储在哈希中。最后,根据哈希元素的计数对它们进行排序。
以下是上述方法的实现–

CPP

// CPP program for above approach
#include 
using namespace std;
 
// Compare function
bool fcompare(pair > p,
              pair > 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 > 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 > > 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 Function
int 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;
}

Python3

# 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 Function
if __name__ == "__main__":
    arr = [2, 5, 2, 6, -1, 9999999, 5, 8, 8, 8]
    n = len(arr)
    solution = sortByFreq(arr, n)
    print(*solution)

输出

8 8 8 2 2 5 5 6 -1 9999999

这也可以通过使用两个映射来解决,一个映射用于数组元素作为索引,第二个映射之后的键是频率和值是数组元素。

方法3(使用BST和排序)

  • 在BST中一个接一个地插入元素,如果已经存在一个元素,则增加节点的计数。二元搜索树的节点(用于此方法)如下。

C

struct tree {
    int element;
    int first_index /*To handle ties in counts*/
        int count;
} BST;
  • 将BST的第一个索引和相应计数存储在2D数组中。
  • 根据计数对2D数组进行排序(在平局的情况下使用索引)。