🎈 作者:Linux猿
🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C++、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊!
🎈 关注专栏: 数据结构和算法成神路【精讲】优质好文持续更新中……🚀🚀🚀
🎈 欢迎小伙伴们点赞👍、收藏⭐、留言💬
目录
一、题目描述
1.1 输入描述
1.2 输出描述
二、测试样例
三、解题思路
四、代码实现
五、时间复杂度
本文是针对 【数据结构和算法】超详细,超多图解,赫夫曼树详解 中「实战演练」题目的讲解,下面来详细讲解题目 杭电OJ Safe Or Unsafe。
一、题目描述
Javac++ 一天在看计算机的书籍的时候,看到了一个有趣的东西!每一串字符都可以被编码成一些数字来储存信息,但是不同的编码方式得到的储存空间是不一样的!并且当储存空间大于一定的值的时候是不安全的!所以 Javac++ 就想是否有一种方式是可以得到字符编码最小的空间值!显然这是可以的,因为书上有这一块内容--「哈夫曼编码(Huffman Coding)」;一个字母的权值等于该字母在字符串中出现的频率。所以 Javac++ 想让你帮忙,给你安全数值和一串字符串,并让你判断这个字符串是否是安全的 ?
1.1 输入描述
输入有多组 case,首先是一个数字 n 表示有 n 组数据,然后每一组数据是有一个数值 m (integer),和一串字符串没有空格只有包含「小写字母」组成!
1.2 输出描述
如果字符串的编码值小于等于给定的值则输出 yes,否则输出 no。
二、测试样例
输入数据:
2
12
helloworld
66
ithinkyoucandoit
输出数据:
no
yes
说明:2 表示有两组测试样例:
在样例一中,字符串 helloworld 经过「哈夫曼编码」后长度为 27,27 > 12 ,所以输出 no;
在样例二中,字符串 ithinkyoucandoit 经过「哈夫曼编码」后长度为 54,54 < 66,所以输出 yes。
三、解题思路
本题是「赫(哈)夫曼树」的简单应用,假设输入的编码值为 m,经过「哈夫曼编码」后的字符串长度为 ans。
本题解题步骤如下所示:
(1)计算输入字符串中每类字符的个数,当做字符串的权重;
(2)模拟「赫(哈)夫曼树」的建立过程,同时统计经过「哈夫曼编码」后字符串的长度 ans;
(3)比较 m 和 ans 的大小,如果 ans <= m 输出 yes,否则输出 no 即可。
四、代码实现
代码实现如下所示:
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
int main()
{
int T;
cin>>T;
while (T--){
string str;
int n, ch[30];
cin >> n >> str;
memset(ch, 0, sizeof ch);
int num = str.size();
for (int i = 0; i < num; ++i) {
++ch[str[i] - 'a'];
}
priority_queue<int, vector<int>, greater<int> > que;
for (int i = 0; i < 30; ++i) {
if (ch[i]) {
que.push(ch[i]);
}
}
int ans = 0;
if (que.size() == 1){
ans = que.size();
}
while (que.size() > 1){
int t1 = que.top();
que.pop();
int t2 = que.top();
que.pop();
que.push(t1 + t2);
ans += t1 + t2;
}
if (ans <= n) {
cout<<"yes"<<endl;
} else {
cout<<"no"<<endl;
};
}
return 0;
}
五、时间复杂度
时间复杂度:O(n + mlogm)
其中,n 表示字符串的长度, m 表示字符串中字符的种类,需要遍历一遍字符串统计每类字符的个数,时间复杂度为 O(n),然后,「优先队列」求解「哈夫曼编码」,时间复杂度为 O(mlogm),所以总的时间复杂度为 O(n + mlogm)。
🎈 感觉有帮助记得「一键三连」支持下哦!有问题可在评论区留言💬,感谢大家的一路支持!🤞猿哥将持续输出「优质文章」回馈大家!🤞🌹🌹🌹🌹🌹🌹🤞