925. Long Pressed Name*

​https://leetcode.com/problems/long-pressed-name/​

题目描述

Your friend is typing his ​​name​​​ into a keyboard. Sometimes, when typing a character ​​c​​, the key might get long pressed, and the character will be typed 1 or more times.

You examine the ​​typed​​​ characters of the keyboard. Return ​​True​​ if it is possible that it was your friends name, with some characters (possibly none) being long pressed.

Example 1:

Input: name = "alex", typed = "aaleex"
Output: true
Explanation: 'a' and 'e' in 'alex' were long pressed.

Example 2:

Input: name = "saeed", typed = "ssaaedd"
Output: false
Explanation: 'e' must have been pressed twice, but it wasn't in the typed output.

Example 3:

Input: name = "leelee", typed = "lleeelee"
Output: true

Example 4:

Input: name = "laiden", typed = "laiden"
Output: true
Explanation: It's not necessary to long press any character.

Note:

  • ​name.length <= 1000​
  • ​typed.length <= 1000​
  • The characters of​​name​​​ and​​typed​​ are lowercase letters.

C++ 实现 1

本题先介绍讨论区的一种方法, 写法看起来简洁, 但是我感觉, 如果让我再一次写这道题, 我可能仍无法写成下面的样子. 之后的 ​​C++ 实现 2​​​ 以及 ​​C++ 实现 3​​ 介绍按我的思路所实现的代码.

下面代码来自: ​​[C++/Java/Python] Two Pointers​​, 使用双指针.

思路可以概括为: 如果 ​​name[i] == typed[j]​​​, 那么指针 ​​i​​​ 和 ​​j​​​ 同时向后移动. 否则, 如果 ​​j == 0​​​ 或者 ​​typed[j] != typed[j - 1]​​​ 时, 直接返回 false, 这说明当前字符不是 long pressed 的. 但如果 ​​typed[j] == typed[j - 1]​​​, 那么移动指针 ​​j​​.

class Solution {
public:
bool isLongPressedName(string name, string typed) {
int i = 0, m = name.length(), n = typed.length();
for (int j = 0; j < n; ++j)
if (i < m && name[i] == typed[j])
++i;
else if (!j || typed[j] != typed[j - 1])
return false;
return i == m;
}
};

C++ 实现 2

我的实现, ​​beats 100%​​. 思路也是双指针, 但基于如下考虑:

  • ​name​​​ 的长度肯定小于或等于​​typed​​ 的长度, long pressed 的字符串肯定更长;
  • 对​​name​​​ 和​​typed​​​ 遍历, 如果​​name[i] == typed[j]​​, 那么两个指针同时向右移动.
  • 如果​​name[i] != typed[j]​​​, 那么由于​​typed​​​ 是 long pressed 的字符, 如果​​type[j] == type[j - 1]​​​, 就要一直向右移动​​j​​​, 找到第一个使​​typed[j] != typed[j - 1]​​​ 的​​j​​​, 再判断此时​​typed[j]​​​ 是否等于​​name[i]​​​, 如果相等, 那么​​i​​​ 和​​j​​ 仍要继续移动.
class Solution {
public:
bool isLongPressedName(string name, string typed) {
if (name.size() > typed.size()) return false;
int j = 0;
for (int i = 0; i < name.size(); ++ i) {
if (name[i] != typed[j]) {
while (j - 1 >= 0 && typed[j - 1] == typed[j]) ++ j;
if (typed[j] != name[i]) return false;
}
++ j;
}
return true;
}
};

C++ 实现 3

不想解析了, 思路反正很暴力.

class Solution {
public:
bool isLongPressedName(string name, string typed) {
if (name.size() > typed.size()) return false;
int i = 0, j = 0;
while (i < name.size() && j < typed.size()) {
if (name[i] != typed[j]) return false;
else {
int prev_i = i, prev_j = j;
while (i + 1 < name.size() && name[i + 1] == name[i]) ++ i;
while (j + 1 < typed.size() && typed[j + 1] == typed[j]) ++ j;
++ i;
++ j;
// 如果 typed[prev_j, ... j) 中重复字母的数量比
// name[prev_i, ..., i) 中的少, 返回 false.
if (j - prev_j < i - prev_i) return false;
}
}
return (i >= name.size() && j >= typed.size());
}
};