Given two strings s
and t
, return true
if s
is a subsequence of t
, or false
otherwise.
A subsequence of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (i.e., "ace"
is a subsequence of "abcde"
while "aec"
is not).
Example 1: Input: s = "abc", t = "ahbgdc" Output: true
Example 2: Input: s = "axc", t = "ahbgdc" Output: false
Follow up: Suppose there are lots of incoming s
, say s1, s2, ..., sk
where k >= 10^9
, and you want to check one by one to see if t
has its subsequence. In this scenario, how would you change your code?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method for determining if one string is a subsequence of another involves checking every possible way the first string could appear within the second. Essentially, we're trying all combinations to see if we can find the characters of the first string in the correct order within the second string.
Here's how the algorithm would work step-by-step:
def is_subsequence_brute_force(subsequence, main_string):
subsequence_index = 0
main_string_index = 0
while subsequence_index < len(subsequence) and main_string_index < len(main_string):
# If characters match, move to next char in subsequence
if subsequence[subsequence_index] == main_string[main_string_index]:
subsequence_index += 1
# Always move to the next char in the main string
main_string_index += 1
# Check if we've reached the end of the subsequence
if subsequence_index == len(subsequence):
return True
else:
return False
We want to check if one string appears in order within another. The best way to do this is to walk through both strings at the same time, looking for matching letters and advancing through both strings, or only the second string, as needed.
Here's how the algorithm would work step-by-step:
def is_subsequence(subsequence_string, main_string):
subsequence_pointer = 0
main_string_pointer = 0
while subsequence_pointer < len(subsequence_string) and \
main_string_pointer < len(main_string):
# If chars match, advance both pointers
if subsequence_string[subsequence_pointer] == main_string[main_string_pointer]:
subsequence_pointer += 1
# Always advance main string pointer
main_string_pointer += 1
# If we reached the end of subsequence, it's a subsequence
if subsequence_pointer == len(subsequence_string):
return True
return False
Case | How to Handle |
---|---|
s is an empty string | An empty string is always a subsequence of any other string, so return true. |
t is an empty string but s is not | If s is not empty and t is empty, s cannot be a subsequence of t, so return false. |
Both s and t are empty strings | An empty string is a subsequence of another empty string, return true. |
s is longer than t | If s is longer than t, s cannot be a subsequence of t, so return false. |
s and t are identical strings | Identical strings satisfy the subsequence condition, return true. |
t is a very long string, but s is a short string at the very end of t | The iterative approach handles this by scanning t until the matching characters of s are found or t is exhausted. |
s contains duplicate characters. | The iterative approach handles this by searching through t for each character in s independently. |
s contains characters not found in t. | The algorithm will eventually fail to find the character in t, returning false. |