目录
前言
仅个人记录所用
源自卡码网的C++基础课
“这门C++基础课 帮助 编程零基础学员快速学习刷算法题所需要的基础语法知识,学完之后,再来刷代码随想录,或者自己去刷编程题,基本不会有语法方面的困惑了,可以帮助大家快速上手刷题。 ”
第十六题包含以下内容:
- 哈希表的概念和特点
- 数组作为哈希表的使用
一、题目描述
题目描述:
给定一个只包含小写字母的字符串,统计字符串中每个字母出现的频率,并找出出现频率最高的字母,如果最高频率的字母有多个,输出字典序靠前的那个字母。
输入描述:
包含多组测试数据,每组测试数据占一行。
输出描述:
有多组输出,每组输出占一行。
输入示例:
2
abcdeef
aabbccddeeff
输出示例:
e
a
二、解题思路
1.哈希表
哈希表是根据关键码key
的值而直接进行访问的数据结构。
哈希表的作用是快速判断一个元素是否出现在集合里,它的核心思想是在关键码和存储位置之间建立一个确定的对应关系f
, 使得每个关键字key
对应一个存储位置,而这个对应关系,称之为散列函数(哈希函数)。
其实数组就是一张哈希表,哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。
哈希表来解决问题的时候,一般选择以下三种数据结构。
- 数组
set
集合map
映射
哈希表可以将其比喻为一个大抽屉,抽屉里面有很多小格子。每个格子可以用来存放一些东西。
- 抽屉编号: 抽屉有编号,这个编号就是数据的
key
,我们通过这个key
来找到对应的抽屉。 - 散列函数: 哈希表使用一种特殊的函数(哈希函数),来决定数据应该放在哪个抽屉里。这个函数将数据的名字
key
转换成一个数字,然后根据这个数字来选择一个抽屉。 - 抽屉里的物品: 在每个抽屉里,可以放一些东西,这些东西就是我们要存储的数据。
- 解决冲突: 有时候不同的
key
经过散列函数后可能会得到相同的编号,这就是冲突。哈希表有方法来处理这些冲突。 - 快速查找: 当我们需要找到某个数据时,哈希表可以通过名字
key
快速地找到对应的抽屉,然后取出里面的数据,这个操作非常快速,就像从抽屉中拿出东西一样。
2.哈希表-数组
数组可以作为简单哈希表来使用,所以我们可以定义一个数组,来记录字符串s当中字符出现的次数。
由于输入的全都是小写字母,小写字母只有26个,那我们定义一个长度为26的数组即可,字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。
在遍历 字符串s的时候,只需要将s[i] - 'a'
所在的索引做+1 操作即可,并不需要记住字符a的ASCII,只要求出一个相对数值就可以了。 这样就将字符串s中字符出现的次数,统计出来了
// 统计各个字符出现的频率
for (int i = 0; i < s.size(); i++) {
count[s[i] - 'a']++;
}
经过一轮遍历之后已经完成统计,数组中各位的元素已经是a-z
字母的频次了,如果想要找到最大值,还是需要重新遍历一遍,那我们如何记录这个最大值呢?
只需要先初始化最大值,然后逐一比对字符出现的频次和当前最大值的大小,如果当前字符出现的频次大于最大值,则更新最大值为当前字符出现的频次,这样完整遍历一遍后,就能找到出现频次最大的字符。
三、完整代码
#include <iostream>
#include <string>
using namespace std;
int main() {
int n;
string s;
while (cin >> n) { // 题目中说包含多组测试数据,所以这里要持续输入
while (n--) {
cin >> s; // 输入字符串
int count[26] = {0};
// 统计各个字符出现的频率
for (int i = 0; i < s.size(); i++) {
count[s[i] - 'a']++;
}
int flag = 0;
char result;
// 找到出现频率最大的字符
for (int i = 0; i < 26; i++) {
if (count[i] > flag) {
flag = count[i];
result = i + 'a';
}
}
cout << result << endl;
}
}
}
总结
学习到了数组作为哈希表的使用