Is Subsequence — Solution in Python, Java & C++
Is Subsequence solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript. An easy problem.
Is Subsequence is an easy coding problem on strings, dynamic programming and two pointers.
- Difficulty: Easy
- Topics: Strings, Dynamic Programming, Two Pointers
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
Given two strings s and t, return true if s is a subsequence of t — obtainable from t by deleting some (possibly zero) characters without changing the order of the rest.
Example 1
Input: s = "abc", t = "ahbgdc"
Output: true
Example 2
Input: s = "axc", t = "ahbgdc"
Output: false
Constraints
0 <= s.length <= 100 <= t.length <= 30Lowercase English letters.
Hints for Is Subsequence
Hint 1
Walk through t once, advancing a pointer into s on every match.
Hint 2
s is a subsequence exactly when the s-pointer reaches the end.
How to solve Is Subsequence
A subsequence keeps order but allows gaps, so matching is greedy: walk t once and, whenever the current character is the one you are waiting for in s, consume it. Taking the earliest possible match is always safe, so no backtracking is ever needed.
Approach
- Keep an index
iintos, starting at zero. - Scan
tfrom left to right. - If
iis still in range andt's current character equalss[i], advancei. - After the scan,
sis a subsequence exactly whenireached the end ofs.
Why it works
Matching s[i] at the earliest opportunity is optimal by an exchange argument: if some valid embedding matches s[i] later, moving that match earlier still leaves every subsequent character of s available — the remaining suffix of t is only larger. So greedy never forfeits a match that exists, meaning failure to consume all of s proves no embedding exists at all.
Complexity
- Time —
O(|t|) - Space —
O(1)
Pitfalls
- Guard
iagainst running past the end ofsbefore comparing, or the last matches read out of bounds. - An empty
sis a subsequence of anything — the checki == |s|handles it with no special case. - Do not advance
ion a mismatch; onlytmoves unconditionally. - Never restart the scan on a mismatch — that is the
O(n·m)trap this greedy avoids.
Reference solution
Python
def isSubsequence(s: str, t: str) -> bool:
i = 0
for ch in t:
if i < len(s) and s[i] == ch:
i += 1
return i == len(s)Java
public static boolean isSubsequence(String s, String t) {
int i = 0;
for (int j = 0; j < t.length(); j++) {
if (i < s.length() && s.charAt(i) == t.charAt(j)) i++;
}
return i == s.length();
}C++
bool isSubsequence(string s, string t) {
size_t i = 0;
for (size_t j = 0; j < t.size(); j++) {
if (i < s.size() && s[i] == t[j]) i++;
}
return i == s.size();
}JavaScript
var isSubsequence = function(s, t) {
let i = 0;
for (const ch of t) {
if (i < s.length && s[i] === ch) i++;
}
return i === s.length;
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 515 strings problems · the whole catalogue
Learn the technique: Strings · Dynamic Programming