我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第9篇文章,根据字符出现频率排序 [尽量使用数组来实现 栈 / hash] - 掘金 (juejin.cn)
前言
尽量用数组模拟栈 / hash,虽然数组也属于类级别,但是其处于JVM层面,比一般的HashMap / Stack类要快很多。
一、根据字符出现频率排序
二、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,养成好习惯。可以在运行前顺一遍代码逻辑过程。