题面
题面不说了,简而言之就是在O(N)的时间内求Huffman树。
题解
首先,求Huffmam树最基本的,每次要在集合里找到最小的,这其实就包含了排序。也就是说,在之前O(NlogN) 的方法中,我们处理的问题的一个子问题就是排序。既然要排序,还要O(N)时间,那肯定是要桶排。
考虑如何把排序的过程从之前的过程中提取出来,优先算完,再算其他的。可以排完序,然后把序列前两个(默认是二叉Huffman树)取出来求和再加入序列,然后不断重复这个过程,直到序列中只有一个元素为止。再加入队列的过程可以用二分来O(NlogN)实现,但这并不是最快的。
可以把需要插入队列的元素当成一个集合,在每次计算答案(把序列前两个取出来求和)就相当于把(序列和集合中的元素)(断句)的前两个取出来求和再加入集合,只需要把每个集合中的数与序列第一个作比较,选出最小的。由于集合中的数最多有(N-1) 个,所以复杂度O(N^2)。
但是,如果能够把集合中的数排序,那每次就只需要比较集合中最大的和序列中最大的就好了,复杂度又变成了O(NlogN)(排序logN)。
这个时候,我们会发现,每次加入集合的数总是比上次加入集合的数大(可以理解为序列 { a 1 , a 2 , a 3 , a 4 . . . . . } \{a_1,a_2,a_3,a_4.....\} { a1,a2,a3,a4.....}, a 1 < a 2 < a 3 < a 4 < . . . . a_1<a_2<a_3<a_4<.... a1