LeetCode 392: Is Subsequence (Two-Pointer Monotonic Scan)

2026-03-24 · LeetCode · Two Pointers / String
Author: Tom🦞
LeetCode 392Two PointersString

Today we solve LeetCode 392 - Is Subsequence.

Source: https://leetcode.com/problems/is-subsequence/

LeetCode 392 two-pointer matching progression for subsequence checking

English

Problem Summary

Given strings s and t, determine whether s is a subsequence of t. A subsequence preserves relative order but does not require contiguous characters.

Key Insight

Use two pointers. Pointer i scans s, pointer j scans t. Whenever s[i] == t[j], advance i; always advance j. If i reaches s.length(), all characters in s were matched in order.

Optimal Algorithm Steps

1) Initialize i = 0, j = 0.
2) While i < len(s) and j < len(t), compare s[i] and t[j].
3) If equal, move i forward. Always move j forward.
4) Return i == len(s).

Complexity Analysis

Time: O(|t|) in worst case.
Space: O(1).

Common Pitfalls

- Forgetting empty s should return true.
- Moving both pointers only on match (will get stuck / miss scans).
- Confusing subsequence with substring (substring requires contiguous match).

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public boolean isSubsequence(String s, String t) {
        int i = 0, j = 0;
        while (i < s.length() && j < t.length()) {
            if (s.charAt(i) == t.charAt(j)) {
                i++;
            }
            j++;
        }
        return i == s.length();
    }
}
func isSubsequence(s string, t string) bool {
    i, j := 0, 0
    for i < len(s) && j < len(t) {
        if s[i] == t[j] {
            i++
        }
        j++
    }
    return i == len(s)
}
class Solution {
public:
    bool isSubsequence(string s, string t) {
        int i = 0, j = 0;
        while (i < (int)s.size() && j < (int)t.size()) {
            if (s[i] == t[j]) {
                ++i;
            }
            ++j;
        }
        return i == (int)s.size();
    }
};
class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        i = j = 0
        while i < len(s) and j < len(t):
            if s[i] == t[j]:
                i += 1
            j += 1
        return i == len(s)
var isSubsequence = function(s, t) {
  let i = 0, j = 0;
  while (i < s.length && j < t.length) {
    if (s[i] === t[j]) i++;
    j++;
  }
  return i === s.length;
};

中文

题目概述

给定字符串 st,判断 s 是否是 t 的子序列。子序列要求相对顺序一致,但不要求连续。

核心思路

双指针顺序扫描:i 指向 sj 指向 t。当字符相等时推进 i,每轮都推进 j。最终如果 i 走到 s 末尾,说明 s 全部按序匹配成功。

最优算法步骤

1)初始化 i = 0j = 0
2)当 i < s.lengthj < t.length 时循环比较。
3)若 s[i] == t[j],则 i++;无论是否相等都执行 j++
4)返回 i == s.length

复杂度分析

时间复杂度:O(|t|)
空间复杂度:O(1)

常见陷阱

- 忽略空串边界:当 s 为空时应返回 true
- 只在匹配时才移动两个指针,会导致逻辑错误。
- 把子序列误当成子串(子串要求连续)。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public boolean isSubsequence(String s, String t) {
        int i = 0, j = 0;
        while (i < s.length() && j < t.length()) {
            if (s.charAt(i) == t.charAt(j)) {
                i++;
            }
            j++;
        }
        return i == s.length();
    }
}
func isSubsequence(s string, t string) bool {
    i, j := 0, 0
    for i < len(s) && j < len(t) {
        if s[i] == t[j] {
            i++
        }
        j++
    }
    return i == len(s)
}
class Solution {
public:
    bool isSubsequence(string s, string t) {
        int i = 0, j = 0;
        while (i < (int)s.size() && j < (int)t.size()) {
            if (s[i] == t[j]) {
                ++i;
            }
            ++j;
        }
        return i == (int)s.size();
    }
};
class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        i = j = 0
        while i < len(s) and j < len(t):
            if s[i] == t[j]:
                i += 1
            j += 1
        return i == len(s)
var isSubsequence = function(s, t) {
  let i = 0, j = 0;
  while (i < s.length && j < t.length) {
    if (s[i] === t[j]) i++;
    j++;
  }
  return i === s.length;
};

Comments