
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。
一、题目描述
给定一个只包含大小写英文字母的字符串,请实现字符串压缩编码功能。
压缩规则:
- 如果字符连续出现次数大于 1,则用字符加上出现次数表示
- 如果字符连续出现次数等于 1,则直接输出字符
二、输入描述
- 输入一行,包含一个字符串 str(长度 1 ≤ |str| ≤ 1000)
- 字符串只包含大小写英文字母
三、输出描述
输出压缩后的字符串
四、测试用例
测试用例1:
1、输入
aabcccccaaa
2、输出
a2bc5a3
3、说明
测试多个连续段,同时包含次数为 1 和大于 1 的情况
测试用例2:
1、输入
AAbB
2、输出
A2bB
3、说明
测试大小写敏感,b 和 B 是不同字符
五、解题思路
使用一次线性扫描。
维护一个变量 count,表示当前字符连续出现的次数。从字符串第二个字符开始:
当前字符与前一个字符相同:count++。
不相同:说明上一段连续字符结束,将“字符 + 次数”加入结果;如果次数为 1,只加入字符。
遍历结束后,最后一段字符还没有处理,需要额外加入结果。
Java 中使用 StringBuilder 保存压缩结果,因为字符串在构造过程中需要频繁追加,StringBuilder 比反复使用 String + String 更高效。
时间复杂度为 O(n),字符串只遍历一次;额外空间复杂度为 O(n),用于保存最终结果。
六、Python算法源码
s = input().strip()
# 使用列表保存压缩后的各个部分,
# 最后通过 join 一次性拼接成字符串
result = []
# 当前连续字符出现的次数
count = 1
# 从第二个字符开始扫描
for i in range(1, len(s)):
if s[i] == s[i - 1]:
# 当前字符和前一个字符相同,属于同一个连续段
count += 1
else:
# 上一个连续字符段结束,先保存字符
result.append(s[i - 1])
# 出现次数大于 1 时才添加数字
if count > 1:
result.append(str(count))
# 当前字符开始一个新的连续段
count = 1
# 最后一段字符不会在循环中被处理,因此需要单独添加
result.append(s[-1])
if count > 1:
result.append(str(count))
print(''.join(result))
七、JavaScript算法源码
const fs = require('fs');
// 从标准输入读取字符串
const s = fs.readFileSync(0, 'utf8').trim();
// 使用数组保存结果,最后 join 拼接,
// 避免循环过程中频繁创建新的字符串
const result = [];
let count = 1;
// 从第二个字符开始遍历
for (let i = 1; i < s.length; i++) {
if (s[i] === s[i - 1]) {
// 与前一个字符相同,连续次数增加
count++;
} else {
// 上一个连续字符段已经结束
result.push(s[i - 1]);
// 次数大于 1 时才输出次数
if (count > 1) {
result.push(String(count));
}
// 当前字符开始新的连续段
count = 1;
}
}
// 补上最后一个连续字符段
result.push(s[s.length - 1]);
if (count > 1) {
result.push(String(count));
}
console.log(result.join(''));
八、C算法源码
#include <stdio.h>
#include <string.h>
int main(void) {
// 最大长度为 1000,多预留空间给字符串结束符 '\0'
char str[1005];
if (scanf("%1000s", str) != 1) {
return 0;
}
int n = (int)strlen(str);
// 当前连续字符出现次数
int count = 1;
/*
* 从第二个字符开始扫描。
* 当前字符和前一个字符相同则继续计数;
* 不同则说明上一段连续字符已经结束,可以直接输出。
*/
for (int i = 1; i < n; i++) {
if (str[i] == str[i - 1]) {
count++;
} else {
// 输出上一段字符
putchar(str[i - 1]);
// 连续次数大于 1 时才输出次数
if (count > 1) {
printf("%d", count);
}
// 当前字符开始新的连续段
count = 1;
}
}
/*
* 最后一段字符不会在循环中被输出,
* 因此遍历完成后进行补充处理。
*/
putchar(str[n - 1]);
if (count > 1) {
printf("%d", count);
}
putchar('\n');
return 0;
}
九、C++算法源码
#include <iostream>
#include <string>
using namespace std;
int main() {
string str;
cin >> str;
// 保存最终压缩字符串
string result;
// 当前连续字符的出现次数
int count = 1;
/*
* 线性扫描字符串。
* 如果当前字符等于前一个字符,则继续累计次数;
* 否则上一段连续字符结束,将其加入结果。
*/
for (int i = 1; i < (int)str.size(); i++) {
if (str[i] == str[i - 1]) {
count++;
} else {
// 添加上一段对应的字符
result += str[i - 1];
// 连续次数超过 1 时,才需要添加次数
if (count > 1) {
result += to_string(count);
}
// 当前字符开始一个新的连续段
count = 1;
}
}
/*
* 最后一段不会触发“字符发生变化”的条件,
* 所以必须在循环结束以后单独处理。
*/
result += str.back();
if (count > 1) {
result += to_string(count);
}
cout << result << '\n';
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 新系统 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。

45万+

被折叠的 条评论
为什么被折叠?



