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

📅  最后修改于: 2023-12-03 15:25:55.008000             🧑  作者: Mango

按频率对元素进行排序|套装2

本套装提供了多种不同的算法实现,用于对元素按照出现频率进行排序。这些算法包括桶排序、最小堆、Map+优先队列,各有不同的优劣点,适用于不同的场景。在本套装中,你可以根据自己的需要来选择最合适的算法。

桶排序

桶排序是一种简单而又高效的算法,适用于元素数量较大,但元素值的范围比较小的情况。该算法首先统计每个元素的出现次数,然后根据出现次数将元素分配到各个桶中,最后按照桶的顺序将元素输出即可。

public static int[] frequencySort(int[] nums) {
    int n = nums.length;
    Map<Integer, Integer> freq = new HashMap<>();
    for (int num : nums) {
        freq.put(num, freq.getOrDefault(num, 0) + 1);
    }
    List<Integer>[] buckets = new ArrayList[n + 1];
    for (int key : freq.keySet()) {
        int f = freq.get(key);
        if (buckets[f] == null) {
            buckets[f] = new ArrayList<>();
        }
        buckets[f].add(key);
    }
    int[] res = new int[n];
    int idx = 0;
    for (int i = n; i >= 0; i--) {
        if (buckets[i] != null) {
            for (int num : buckets[i]) {
                for (int j = 0; j < i; j++) {
                    res[idx++] = num;
                }
            }
        }
    }
    return res;
}
最小堆

最小堆是一种可以快速维护最小值的数据结构,适用于元素数量较大,但元素值的范围比较大的情况。该算法首先统计每个元素的出现次数,并将元素和出现次数封装成一个元素对象,然后将这些对象插入到最小堆中,按照最小堆的顺序依次取出对象中的元素即可。

public static int[] frequencySort(int[] nums) {
    int n = nums.length;
    Map<Integer, Integer> freq = new HashMap<>();
    for (int num : nums) {
        freq.put(num, freq.getOrDefault(num, 0) + 1);
    }
    PriorityQueue<Element> pq = new PriorityQueue<>();
    for (int key : freq.keySet()) {
        pq.offer(new Element(key, freq.get(key)));
    }
    int[] res = new int[n];
    int idx = 0;
    while (!pq.isEmpty()) {
        Element elem = pq.poll();
        for (int i = 0; i < elem.freq; i++) {
            res[idx++] = elem.val;
        }
    }
    return res;
}

static class Element implements Comparable<Element> {
    int val;
    int freq;

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

    public int compareTo(Element other) {
        return Integer.compare(this.freq, other.freq);
    }
}
Map+优先队列

Map+优先队列的算法可以看作是桶排序和最小堆算法的综合体,可以适用于包含重复元素和较大元素范围的情况。该算法先将元素和出现次数封装成一个元素对象,然后利用Map统计每个元素的出现次数,并根据出现次数将元素对象分配到对应的队列中。最后按照队列的顺序依次取出元素即可。

public static int[] frequencySort(int[] nums) {
    int n = nums.length;
    Map<Integer, Integer> freq = new HashMap<>();
    for (int num : nums) {
        freq.put(num, freq.getOrDefault(num, 0) + 1);
    }
    Map<Integer, Queue<Element>> map = new HashMap<>();
    for (int key : freq.keySet()) {
        Element elem = new Element(key, freq.get(key));
        if (!map.containsKey(elem.freq)) {
            map.put(elem.freq, new LinkedList<>());
        }
        map.get(elem.freq).offer(elem);
    }
    int[] res = new int[n];
    int idx = 0;
    for (int i = n; i >= 0; i--) {
        if (map.containsKey(i)) {
            while (!map.get(i).isEmpty()) {
                Element elem = map.get(i).poll();
                for (int j = 0; j < elem.freq; j++) {
                    res[idx++] = elem.val;
                }
            }
        }
    }
    return res;
}

static class Element {
    int val;
    int freq;

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

以上就是本套装提供的排序算法的介绍。你可以按照自己的需求选择最合适的算法。