根据字符出现频率排序 [尽量使用数组来实现 栈 / hash]

271 阅读1分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第9篇文章,根据字符出现频率排序 [尽量使用数组来实现 栈 / hash] - 掘金 (juejin.cn)

前言

尽量用数组模拟栈 / hash,虽然数组也属于类级别,但是其处于JVM层面,比一般的HashMap / Stack类要快很多。

一、根据字符出现频率排序

image.png

二、hash记录+优先队列排序+stringbuilder串联字符

1、hashMap版

/*
    target:将字符出现频次最多的字符一起打包防在前面。
    1-统计字符出现的频次;
    2-按频次来对字符排序,需要保存字符频次信息。
    3-用StringBuilder来连接从高到低的字符。
    */
    public String frequencySort(String s) {
        char[] arr = s.toCharArray();
        Map<Integer, Integer> fx = new HashMap<>();

        for (char c : arr) fx.put((int) c, fx.getOrDefault((int) c, 0) + 1);

        PriorityQueue<int[]> que = new PriorityQueue<>((p, q) -> q[1] - p[1]);
        Set<Map.Entry<Integer, Integer>> entries = fx.entrySet();
        for (Map.Entry<Integer, Integer> entry : entries) que.add(new int[]{entry.getKey(), entry.getValue()});

        StringBuilder sb = new StringBuilder();
        while (!que.isEmpty()) {
            int[] el = que.poll();

            produceString(sb, el);
        }
        return sb.toString();
    }

    private void produceString(StringBuilder sb, int[] el) {
        char ch = (char) el[0];
        int n = el[1];

        for (int i = 0; i < n; i++) sb.append(ch);
    }

2、数组hash版

/*
    target:将字符出现频次最多的字符一起打包放在前面。
    1-统计字符出现的频次;
    2-按频次来对字符排序,需要保存字符频次信息。
    3-用StringBuilder来连接从高到低的字符。
    */
    public String frequencySort(String s) {
        char[] arr = s.toCharArray();
        int[] fx = new int[256];// 大小写字母/数字。

        for (char c : arr) ++fx[c];

        PriorityQueue<int[]> que = new PriorityQueue<>(Comparator.comparing(p -> -p[1]));
        for (int i = 0;i < 256;i++) if(fx[i] != 0)que.add(new int[]{i,fx[i]});

        StringBuilder sb = new StringBuilder();
        while (!que.isEmpty()) {
            int[] el = que.poll();

            produceString(sb, el);// append n个字符。
        }
        return sb.toString();
    }

    private void produceString(StringBuilder sb, int[] el) {
        char ch = (char) el[0];
        int n = el[1];

        for (int i = 0; i < n; i++) sb.append(ch);
    }

总结

1)hash / PriorityQueue / StringBuilder的基本使用。

2)尽量用数组模拟栈 / hash,虽然数组也属于类级别,但是其处于JVM层面,比一般的HashMap / Stack类要快很多。

3)一个题,从确定好需求,再分析并拆解步骤,最后边注解边coding,养成好习惯。可以在运行前顺一遍代码逻辑过程。

参考文献

[1] LeetCode 根据字符出现频率排序