請設計一個算法,給一個字符串進行二進制編碼,使得編碼後字符串的長度最短。java
每組數據一行,爲待編碼的字符串。保證字符串長度小於等於1000。
一行輸出最短的編碼後長度。
MT-TECH-TEAM
33
import java.util.Comparator; import java.util.HashMap; import java.util.Map.Entry; import java.util.PriorityQueue; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { String s = scanner.next(); System.out.println(createHuffman(s)); } } public static int createHuffman(String s) { char[] chars = s.toCharArray(); //hash表存放每一個字符和出現的次數(出現的次數就是權重) HashMap<Character, Integer> map = new HashMap<Character, Integer>(); for(int i=0;i<chars.length;i++){ if(map.containsKey(chars[i])){ map.put(chars[i], map.get(chars[i]) + 1); } else{ map.put(chars[i], 1); } } //優先隊列(最小推),每次能獲得weigh最小的node PriorityQueue<HuffmanNode> queue = new PriorityQueue<>(map.size(), new Comparator<HuffmanNode>() { @Override public int compare(HuffmanNode o1, HuffmanNode o2) { // TODO Auto-generated method stub return o1.weight - o2.weight; } }); //構建哈夫曼樹合併兩個權重最小的節點,直到只剩下根節點root for(Entry<Character, Integer> entry : map.entrySet()){ queue.offer(new HuffmanNode(entry.getValue(), entry.getKey())); } while(queue.size() > 1){ //彈出兩個權重最小的,合併爲一個node HuffmanNode leftNode = queue.poll(); HuffmanNode rightNode = queue.poll(); HuffmanNode fatherNode = new HuffmanNode(leftNode.weight + rightNode.weight); fatherNode.left = leftNode; fatherNode.right = rightNode; queue.offer(fatherNode); } HuffmanNode root = queue.poll(); return getLength(root, 0); } public static int getLength(HuffmanNode node, int depth) { if(node == null){ //僅計算ch有值的 return 0; } return (node.ch == null ? 0:node.weight)*depth + getLength(node.left, depth+1) + getLength(node.right, depth+1); } } class HuffmanNode{ int weight;//權重(字符出現次數) HuffmanNode left; HuffmanNode right; Character ch; //若是是初始字符,則ch爲字符,若是是合併的,則爲null public HuffmanNode(int weight) { super(); this.weight = weight; } public HuffmanNode(int weight, char ch) { super(); this.weight = weight; this.ch = ch; } }