1. 项目背景与核心需求
华为OD(Huawei Outsourcing Development)机考作为华为技术人才选拔的重要环节,其双机位监考系统下的C卷题库以算法题为主,其中"简单的解压缩算法"是高频考察题目之一。这道题要求考生在限定时间内,使用指定编程语言实现特定规则的字符串解压缩功能,主要考察以下能力:
- 字符串处理的基本功(索引操作、正则匹配等)
- 栈结构在嵌套场景下的应用能力
- 多语言基础语法的熟练程度
- 边界条件处理的严谨性
实际业务中,类似算法可用于:
- 日志文件的压缩存储与快速检索
- 网络传输中的轻量级数据压缩
- 嵌入式设备资源受限环境下的数据处理
2. 题目解析与算法设计
2.1 题目示例说明
给定压缩字符串格式为字母[数字],例如:
a3[b]→abbbb2[a2[c]]→baccacc2[abc]3[cd]ef→abcabccdcdcdef
2.2 核心算法思路
采用双栈解法(数字栈+字符串栈):
python复制def decompress(s):
num_stack = []
str_stack = []
current_str = ''
current_num = 0
for char in s:
if char.isdigit():
current_num = current_num * 10 + int(char)
elif char == '[':
num_stack.append(current_num)
str_stack.append(current_str)
current_num = 0
current_str = ''
elif char == ']':
num = num_stack.pop()
prev_str = str_stack.pop()
current_str = prev_str + current_str * num
else:
current_str += char
return current_str
2.3 多语言实现要点
Java版本
java复制public String decompress(String s) {
Stack<Integer> numStack = new Stack<>();
Stack<StringBuilder> strStack = new Stack<>();
StringBuilder current = new StringBuilder();
int num = 0;
for(char c : s.toCharArray()) {
if(Character.isDigit(c)) {
num = num * 10 + (c - '0');
} else if(c == '[') {
numStack.push(num);
strStack.push(current);
current = new StringBuilder();
num = 0;
} else if(c == ']') {
int k = numStack.pop();
StringBuilder temp = strStack.pop();
current = temp.append(current.toString().repeat(k));
} else {
current.append(c);
}
}
return current.toString();
}
C++版本
cpp复制string decompress(string s) {
stack<int> num_stack;
stack<string> str_stack;
string current;
int num = 0;
for(char c : s) {
if(isdigit(c)) {
num = num * 10 + (c - '0');
} else if(c == '[') {
num_stack.push(num);
str_stack.push(current);
current = "";
num = 0;
} else if(c == ']') {
int k = num_stack.top(); num_stack.pop();
string prev = str_stack.top(); str_stack.pop();
string temp;
for(int i=0; i<k; ++i) temp += current;
current = prev + temp;
} else {
current += c;
}
}
return current;
}
3. 关键难点与优化策略
3.1 嵌套处理陷阱
当遇到3[a2[c]]这类嵌套场景时,需要注意:
- 内层
]弹出栈时只处理当前层级的字符串 - 外层
]处理时要保留之前栈中的上下文
3.2 性能优化技巧
-
字符串拼接优化:
- Java/C#使用StringBuilder
- Python使用join()代替+=
- Go使用bytes.Buffer
-
数字处理优化:
javascript复制// 错误示范 num += parseInt(char); // 正确写法 num = num * 10 + parseInt(char);
3.3 特殊边界案例
需要额外测试的case:
- 空字符串输入
- 没有压缩的原始字符串
- 多重嵌套(超过3层)
- 数字0作为系数的情况
- 压缩块连续出现(如
2[a]3[b])
4. 双机位考试实战技巧
4.1 环境准备要点
- 提前测试IDE的代码补全功能是否可用
- 准备常用算法模板(栈操作、字符串处理等)
- 确认多语言输入输出语法差异
4.2 调试技巧
- 使用console.log/print逐步输出中间变量
- 对每个
[和]标记打印当前栈状态 - 准备可视化调试用例:
code复制输入:a2[b3[c]d] 过程: a -> [ -> b -> [ -> ccc ] -> d -> ] -> bcccd -> abbcccd
4.3 时间分配建议
- 读题分析:5分钟
- 基础实现:15分钟
- 边界测试:8分钟
- 优化调整:7分钟
- 最终检查:5分钟
5. 不同语言实现对比
| 特性 | Java | Python | JavaScript | Go |
|---|---|---|---|---|
| 字符串拼接 | StringBuilder | join() | += | bytes.Buffer |
| 栈实现 | Stack类 | list | array | slice |
| 数字解析 | Character | int() | parseInt | strconv |
| 执行效率 | 高 | 中等 | 较低 | 极高 |
| 代码量 | 较多 | 较少 | 中等 | 中等 |
实际考试中选择最熟悉的语言,Python版本通常代码量最少但需要注意时间复杂度
6. 常见错误排查指南
-
数字连续位处理错误:
javascript复制// 错误示例 if(isdigit(c)) num = c - '0'; // 正确应累积数字 -
栈空弹出异常:
python复制# 必须检查栈非空 if num_stack and char == ']': k = num_stack.pop() -
字符串顺序颠倒:
go复制// 注意拼接顺序 current = strStack[len(strStack)-1] + strings.Repeat(current, k) -
Unicode字符处理:
java复制// 处理非ASCII字符时需要特别注意 Character.isLetter(c) -
内存溢出问题:
- C++版本要注意字符串拷贝开销
- 递归解法在深度嵌套时可能爆栈
7. 进阶变形题目
7.1 支持转义字符
处理包含\的字符串,如a2[b\[c]] → ab[c]b[c]
解决方案:
- 添加转义状态标记
- 遇到
\时跳过下一个字符的特殊解析
7.2 多字符系数
支持10[abc]这样的多数字系数
只需改进数字累积逻辑:
python复制while i < len(s) and s[i].isdigit():
num = num * 10 + int(s[i])
i += 1
7.3 嵌套深度限制
添加最大嵌套深度限制(如100层),超过则报错
实现方式:
java复制if(stack.size() > MAX_DEPTH) {
throw new RuntimeException("Exceed max depth");
}
在实际开发中遇到类似需求时,建议优先考虑:
- 使用标准库(如Java的java.util.zip)
- 评估第三方成熟组件(如zlib)
- 仅在极端资源受限场景下手写算法
