A subsequence of a string is a new string generated by deleting some (or no) characters from the original string without changing the relative order of the remaining characters.
To check if s is a subsequence of t, we can use a Two Pointers approach.
We place one pointer at the start of s and another at the start of t.
We scan through t seeking the character that matches the current character in s.
- If they match, we advance both pointers (we found a letter of
sint). - If they don’t match, we only advance the pointer in
t(keep searchingt). If we successfully advance the pointer forsentirely through the strings, it means all characters ofswere found intin the correct order.
// Pseudocode:
// i = 0 (pointer for s)
// j = 0 (pointer for t)
// While i < s.size() and j < t.size():
// If s[i] == t[j]:
// i += 1
// j += 1
// Return True if i == s.size() else False
#include <string>
class Solution {
public:
bool isSubsequence(std::string s, std::string t) {
int i = 0, j = 0;
while (i < s.size() && j < t.size()) {
// If characters match, advance pointer for s
if (s[i] == t[j]) {
i++;
}
// Always advance pointer for t
j++;
}
// If we successfully traversed all of s, it's a subsequence
return i == s.size();
}
};- Time Complexity:
O(T)whereTis the length of stringt. In the worst-case scenario, we iterate through the entirety oft. - Space Complexity:
O(1). Only two integer pointers (iandj) are used.
sis empty (s = ""): An empty string is mathematically a subsequence of any string. The loop conditioni < s.size()immediately fails (0 < 0 is False), and it returnsi == s.size()(0 == 0 → True). Correct.tis empty (t = "",s = "a"): The loop won’t execute, returns0 == 1→ False. Correct.sis identical tot: Both pointers advance together perfectly, returning True.sis longer thant: The loop will terminate whenjexhaustst.iwill naturally be less thans.size(), returning False.
- Recognition: Checking relative ordering constraints without contiguity implies a Two-Pointer linear scan.
- Follow-up Question handling: What if there are lots of incoming
s, says1, s2, ..., skwherek > 10^9, and you want to check one by one to see ifthas its subsequence?- If
tis huge and we check manysstrings, linear scanO(T)per string is too slow. - Instead, pre-process
t: Create a hash map mapping each character to a sorted list of its indices int. - Then, for each
s, iterate through its characters and use Binary Search (std::upper_bound) on the list of indices to find the next valid index int. This reduces checking eachstoO(len(s) * log(T)).
- If