The "Long Pressed Name" problem asks you to determine whether a string typed
could be a result of someone typing another string name
with possible long presses on some keys. A long press means a character in name
could appear one or more times consecutively in typed
, but the order and sequence of characters must match name
.
Constraints:
name
and typed
are non-empty strings consisting of lowercase English letters.typed
must appear in the same order as in name
.typed
may correspond to one or more of the same character in name
(long press), but not to a different character.name
for different positions in typed
.true
if typed
could have been generated from name
via long presses, or false
otherwise.
At first glance, you might think to compare name
and typed
character by character. However, since long presses are allowed, the same character in name
can appear multiple times consecutively in typed
. This means we need a way to "skip over" repeated characters in typed
as long as they match the current character in name
.
A brute-force approach would try all possible ways to map name
to typed
, but that's inefficient. Instead, a two-pointer technique is suitable: one pointer for name
, and one for typed
. We move through both strings, advancing the pointer in typed
as long as we see valid long presses, and only advance the pointer in name
when we see a match.
The key insight is to ensure all characters in name
are matched in order, and any extra repeated characters in typed
are just valid long presses of the current character.
The optimal solution uses two pointers, i
for name
and j
for typed
:
j
is less than the length of typed
:
name[i]
equals typed[j]
, it’s a match. Advance both pointers.typed[j]
is the same as typed[j-1]
(i.e., a long press of the previous character), advance j
only.false
(the characters don't match and it's not a valid long press).i
has reached the end of name
. If not, some characters in name
were not matched, so return false
.true
.This approach ensures that:
name
is accounted for in typed
in order.typed
are only allowed if they are repeated long presses of the previous character.
Example:
name = "alex"
, typed = "aaleex"
i=0
, j=0
: name[0]='a'
, typed[0]='a'
(match, advance both)i=1
, j=1
: name[1]='l'
, typed[1]='a'
(not match, but typed[1]==typed[0]
: long press, advance j
)i=1
, j=2
: name[1]='l'
, typed[2]='l'
(match, advance both)i=2
, j=3
: name[2]='e'
, typed[3]='e'
(match, advance both)i=3
, j=4
: name[3]='x'
, typed[4]='e'
(not match, but typed[4]==typed[3]
: long press, advance j
)i=3
, j=5
: name[3]='x'
, typed[5]='x'
(match, advance both)i=4
, j=6
: i
has reached the end of name
; success!
The output is true
because every character in name
is matched in order, and extra characters in typed
are valid long presses.
Brute-force approach: Trying all possible mappings would have exponential time complexity and is not feasible for longer strings.
Optimized (two-pointer) approach:
n + m
), where n
is the length of name
and m
is the length of typed
. Each pointer moves forward at most once per character.
The "Long Pressed Name" problem is efficiently solved using a two-pointer technique. By carefully comparing characters and allowing for valid long presses, we ensure that typed
is a possible result of typing name
. The approach is both intuitive and optimal, using linear time and constant space, making it suitable for large inputs. The key insight is to recognize and correctly handle repeated characters as legitimate long presses.
class Solution:
def isLongPressedName(self, name: str, typed: str) -> bool:
i, j = 0, 0
while j < len(typed):
if i < len(name) and name[i] == typed[j]:
i += 1
j += 1
elif j > 0 and typed[j] == typed[j - 1]:
j += 1
else:
return False
return i == len(name)
class Solution {
public:
bool isLongPressedName(string name, string typed) {
int i = 0, j = 0;
while (j < typed.length()) {
if (i < name.length() && name[i] == typed[j]) {
i++;
j++;
} else if (j > 0 && typed[j] == typed[j - 1]) {
j++;
} else {
return false;
}
}
return i == name.length();
}
};
class Solution {
public boolean isLongPressedName(String name, String typed) {
int i = 0, j = 0;
while (j < typed.length()) {
if (i < name.length() && name.charAt(i) == typed.charAt(j)) {
i++;
j++;
} else if (j > 0 && typed.charAt(j) == typed.charAt(j - 1)) {
j++;
} else {
return false;
}
}
return i == name.length();
}
}
var isLongPressedName = function(name, typed) {
let i = 0, j = 0;
while (j < typed.length) {
if (i < name.length && name[i] === typed[j]) {
i++;
j++;
} else if (j > 0 && typed[j] === typed[j - 1]) {
j++;
} else {
return false;
}
}
return i === name.length;
};