2022-6-10 真题练习
校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。描述
请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短。
数据范围:字符串长度满足 1 < n \le 1000 \1<n≤1000 ,本题有多组输入
输入描述:
每组数据一行,为待编码的字符串。保证字符串长度小于等于1000。
输出描述:
一行输出最短的编码后长度。
1 import java.util.HashMap; 2 import java.util.Map; 3 import java.util.PriorityQueue; 4 import java.util.Scanner; 5 6 public class Main { 7 static class TreeNode{ 8 TreeNode left,right; 9 int weight; 10 Character c; 11 TreeNode(int w,char c){ 12 weight=w; 13 this.c=c; 14 } 15 } 16 static int ans; 17 public static void main(String[] args) { 18 Scanner sc = new Scanner(System.in); 19 while (sc.hasNext()){ 20 String s=sc.nextLine(); 21 Map<Character,Integer> map=new HashMap(); 22 for (int i=0;i<s.length();i++){ 23 map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0)+1); 24 } 25 PriorityQueue<TreeNode> queue=new PriorityQueue<>((a,b)->(a.weight- b.weight)); 26 for (Map.Entry<Character, Integer> entry : map.entrySet()) { 27 queue.offer(new TreeNode(entry.getValue(),entry.getKey())); 28 } 29 while (queue.size()>=2){ 30 TreeNode n1=queue.poll(); 31 TreeNode n2=queue.poll(); 32 TreeNode node=new TreeNode(n1.weight+n2.weight,Character.MIN_VALUE); 33 node.left=n1; 34 node.right=n2; 35 queue.offer(node); 36 } 37 TreeNode root=queue.poll(); 38 ans=0; 39 dfs(root,map,0); 40 System.out.println(ans); 41 } 42 43 } 44 45 static public void dfs(TreeNode root,Map<Character,Integer> map,int depth){ 46 if (root==null) { 47 return; 48 } 49 if (map.containsKey(root.c)){ 50 ans+=map.get(root.c)*depth; 51 } 52 dfs(root.left,map,depth+1); 53 dfs(root.right,map,depth+1); 54 } 55 }
思路:编码最佳选择最小生成树,即哈夫曼树。先用hashmap记录不同字符的频率。
再用优先队列构造哈夫曼树:每次挑两个权重最小的合并,将权重和作为新的节点加入到队列中,直到剩下根节点。
深度遍历所有节点,记录节点的深度来计算编码的长度。
浙公网安备 33010602011771号