我正在尝试建立字符的最大堆。首先按频率排序,如果频率相同,则按字母顺序排序。
Map<Character, Integer> map = new HashMap<>();
for(int i = 0; i < n; i++) {
char c = s.charAt(i);
map.put(c, map.getOrDefault(c, 0) + 1);
}
Queue<Character> pq = new PriorityQueue<>(new Comparator<Character>(){
@Override
public int compare(Character c1, Character c2){
if(map.get(c1) == map.get(c2)){
return c1 < c2 ? -1 : (c1 == c2 ? 0 : 1);
//return (char)c1 - (char)c2; same output
}
return map.get(c2) - map.get(c1);
}
});
for(char key : map.keySet()){
pq.offer(key);
System.out.println(key + " has freq " + map.get(key));
}
while(!pq.isEmpty()) {
System.out.print(pq.poll() + " ");
}
我在此maxheap中放入了26个字母,每个字母的频率相同5000。
但是输出顺序为'a','z','y','x'....,'c','b'。
我不明白为什么频率为5000的输出是这样的。如何获得正确的订单?
答案 0 :(得分:3)
鉴于所有频率均相同,则您的if语句错误。您可以使用内置方法比较对象并返回结果
Integer f1 = map.get(c1);
Integer f2 = map.get(c2);
int x = f1.compareTo(f2)
if(x == 0){
return Character.compare(c1, c2);
}
return x;
答案 1 :(得分:1)
您正在通过Integer
与==
语句比较两个if(map.get(c1) == map.get(c2))
实例。它在频率为5时起作用的原因是,对-128…+ 127范围内的自动装箱值进行了强制缓存。当频率为5000时,Integer
对象的身份未指定,相等的对象可能具有不同的身份。
一种解决方法是改用equals。另一个是停止手动实现Comparator
并使用工厂方法。加上其他改进,您的代码可简化为
Map<Character, Integer> map = new HashMap<>();
for(int i = 0; i < n; i++) {
map.merge(s.charAt(i), 1, Integer::sum);
}
Queue<Character> pq = new PriorityQueue<>(
Comparator.<Character>comparingInt(map::get).reversed()
.thenComparing(Comparator.naturalOrder())
);
map.forEach((key, freq) -> {
pq.offer(key);
System.out.println(key + " has freq " + freq);
});
while(!pq.isEmpty()) {
System.out.print(pq.poll() + " ");
}
答案 2 :(得分:0)
您可以使用.equals()方法比较两个对象。它将返回一个布尔值。如果您想进行硬编码比较,则为每个字母分配一个整数值(总共26个变量)并比较它们的整数值,您会知道将哪个放在哪里。