问题描述
小R有一个字符串 word,该字符串由数字和小写英文字母组成。小R想用空格替换每一个不是数字的字符。然后,他希望统计在替换后剩下的整数中,不同整数的数目。
例如,给定字符串 "a123bc34d8ef34",替换后形成的字符串是 " 123 34 8 34",剩下的整数是 "123"、"34"、"8" 和 "34"。不同的整数有三个,即 "123"、"34" 和 "8"。
注意,只有当两个整数的不含前导零的十进制表示不同,才认为它们是不同的整数。
测试样例
样例1:
输入:
word = "a123bc34d8ef34"
输出:3
样例2:
输入:
word = "t1234c23456"
输出:2
样例3:
输入:
word = "a1b01c001d4"
输出:2
问题分析
题目要求:给定一个字符串 word,其中包含数字和小写英文字母。你需要做以下两件事情:
- 用空格替换每个不是数字的字符(即字母)。
- 统计在替换后的字符串中,出现的不同整数的数量。需要注意,整数不能有前导零,且相同数值的整数应该只计数一次。
解题思路
-
提取数字子串:
- 我们首先需要遍历整个字符串,将其中的数字部分提取出来,跳过非数字字符。这里可以利用字符串的遍历和条件判断来提取连续的数字。
-
处理前导零:
- 在提取数字时,我们要注意去掉前导零。比如,
0012和12代表同一个数字。可以利用stoi(字符串转整数)来自动去除前导零。
- 在提取数字时,我们要注意去掉前导零。比如,
-
统计不同的整数:
- 将提取出的整数存储到一个集合(
unordered_set)中,这样集合会自动处理重复的数字。最终集合的大小就是不同整数的个数。
- 将提取出的整数存储到一个集合(
1. 辅助函数:
bool is_num(char c){
return c >= '0' && c <= '9'; // 判断字符是否是数字
}
bool is_word(char c){
return c >= 'a' && c <= 'z'; // 判断字符是否是字母
}
is_num判断一个字符是否为数字。is_word判断一个字符是否为字母。这两个函数基本上是为了让代码更简洁和可读。
2. 核心解题逻辑:
int solution(string word) {
unordered_set<int> hash_num; // 用于记录该数值是否已经出现
int num_count = 0; // 不同整数的个数
int left = 0, right = 0; // 左右指针
while (right < word.size()) {
if (is_num(word[right])) { // 如果字符是数字
if (right + 1 == word.size() || is_word(word[right + 1])) { // 判断当前数字是否是一个完整的数字
int num = stoi(word.substr(left, right - left + 1)); // 提取数字并转化为整数
if (hash_num.find(num) == hash_num.end()) { // 如果数字不在集合中
num_count++; // 计数增加
hash_num.insert(num); // 插入集合
}
left = right + 1; // 更新左指针,指向下一个字符
}
} else { // 如果字符是字母
left++; // 跳过字母
}
right++; // 移动右指针
}
return num_count; // 返回不同整数的个数
}
3. 解释代码逻辑:
unordered_set<int> hash_num用于存储已经处理过的整数。集合保证了整数的唯一性,因此我们只会统计不同的整数。num_count用于记录不同整数的个数。left和right是两个指针,left用来标记数字的起始位置,right用来遍历字符串。每次当遇到一个数字并且到达一个完整数字的结尾时,我们提取这个数字并转换为整数(去掉前导零)。然后,我们检查这个整数是否已经出现过,如果没有,则增加num_count,并将该整数插入unordered_set中。
4. 细节处理:
- 数字的提取: 通过
stoi函数,将字符串中的数字转换为整数时,自动去除前导零。这样,0012和12会被处理为相同的数字。 left和right的更新: 当我们找到一个完整的数字时,left更新为right + 1,准备处理下一个可能的数字。如果right遇到字母,left向后移动一位,跳过当前字母。