原理与步骤
问题描述
判断输入的字符串 typed 是否是名字 name 的长按结果。即 typed 中的字符可以通过长按 name 的某些字符形成,且顺序一致。例如,name = "alex",typed = "aaleex" 返回 true;但 typed = "aaleexa" 返回 false。
解决思路
- 双指针遍历:使用双指针
i和j分别遍历name和typed。 - 字符匹配:若当前字符匹配,则同时移动指针;若不匹配,检查
typed中是否存在长按重复字符。 - 剩余字符检查:遍历完
name后,确保typed剩余字符均为重复字符。
图示法步骤(以 name = "alex",typed = "aaleex" 为例)
| 步骤 | 操作说明 | 指针状态 |
|---|---|---|
| 初始状态 | i=0, j=0,比较 name[0]='a' 和 typed[0]='a' → 匹配 | i=1, j=1 |
| 长按处理 | name[1]='l' vs typed[1]='a' → 不匹配,跳过 typed 中的重复 a | j 移动到 2 |
| 继续匹配 | name[1]='l' vs typed[2]='l' → 匹配 | i=2, j=3 |
| 剩余字符检查 | typed 剩余字符 e 和 e 均为重复,最终返回 true |
代码程序与关键注释
#include <iostream>
#include <string>
using namespace std;
bool isLongPressedName(string name, string typed) {
if (name.empty()) { // 处理 name 为空的情况
return typed.empty();
}
int i = 0, j = 0;
while (i < name.size() && j < typed.size()) {
if (name[i] == typed[j]) { // 字符匹配,同时移动指针
i++;
j++;
} else {
if (j == 0) return false; // 第一个字符不匹配,直接返回false
// 跳过 typed 中的重复字符(长按部分)
while (j < typed.size() && typed[j] == typed[j - 1]) {
j++;
}
// 再次检查是否匹配
if (i < name.size() && j < typed.size() && name[i] == typed[j]) {
i++;
j++;
} else {
return false;
}
}
}
// 检查 name 是否全部匹配
if (i < name.size()) return false;
// 检查 typed 剩余字符是否均为重复字符
while (j < typed.size()) {
if (j > 0 && typed[j] == typed[j - 1]) {
j++;
} else {
return false;
}
}
return true;
}
int main() {
string name, typed;
cin >> name >> typed;
cout << (isLongPressedName(name, typed) ? "true" : "false") << endl;
return 0;
}
时间复杂度与空间复杂度
- 时间复杂度:**O(n + m)**
n和m分别为name和typed的长度,每个字符最多被访问两次。
- 空间复杂度:**O(1)**
- 仅使用固定数量的变量,无额外空间开销。
总结
- 核心思路:
- 双指针遍历,处理长按导致的重复字符,确保顺序和字符一一对应。
- 关键优化:
- 条件顺序调整:避免数组越界,确保先检查索引有效性再访问元素。
- 边界处理:单独处理
name为空的情况,避免非法访问。
- 适用场景:
- 验证用户输入是否符合预期格式,如密码输入、自动补全等场景。
254

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



