判断子序列
字符串 双指针题目描述
给定字符串 s 和 t,判断 s 是否为 t 的子序列。
字符串的子序列是指:通过删除原字符串中的一些(或不删除)字符,在不改变剩余字符相对位置的情况下,得到的新字符串。
示例 1:
- 输入:
s = "abc",t = "ahbgdc" - 输出:
true - 说明:
"abc"是"ahbgdc"的子序列(依次找到a、b、c)
示例 2:
- 输入:
s = "axc",t = "ahbgdc" - 输出:
false - 说明:
t中无法按顺序找到"axc"(有a和c,但中间没有x)
思路分析
这是一道经典的双指针问题,核心思想是:在 t 中按顺序寻找 s 的每个字符。
双指针策略
使用两个指针分别指向 s 和 t 的当前位置:
- 指针
i:指向s的当前待匹配字符 - 指针
j:指向t的当前字符
移动规则
-
当
s[i] === t[j]时:- 说明在
t中找到了s的当前字符 i指针前移(继续匹配s的下一个字符)j指针前移(继续在t中搜索)
- 说明在
-
当
s[i] !== t[j]时:- 当前字符不匹配
i指针不动(继续寻找当前字符)j指针前移(在t的后续字符中继续搜索)
-
终止条件:
- 若
i遍历完s(i === s.length),说明s的所有字符都在t中按顺序找到了,返回true - 若
j遍历完t而i还没遍历完s,说明t中无法找到s的所有字符,返回false
- 若
算法步骤
- 初始化两个指针:
i = 0(指向s),j = 0(指向t) - 当
i < s.length且j < t.length时循环:- 若
s[i] === t[j],则i++(匹配成功,继续匹配下一个) j++(无论是否匹配,t的指针始终前移)
- 若
- 循环结束后,返回
i === s.length(判断s是否完全匹配)
关键点
j指针始终前移:这是算法的核心,确保遍历整个t字符串i指针按需前移:仅在字符匹配时才前移,记录匹配进度- 最终判断:检查
i是否到达s的末尾,而不是检查j是否到达t的末尾
示例代码
复杂度分析
- 时间复杂度:
O(n),其中n是字符串t的长度。最坏情况下需要遍历整个t字符串。 - 空间复杂度:
O(1),只使用了两个指针变量。
示例演示
示例 1:s = "abc", t = "ahbgdc"
结果:i === s.length 为 true,返回 true
示例 2:s = "axc", t = "ahbgdc"
结果:i === 1 !== s.length(s.length === 3),返回 false
示例 3:空字符串 s = "", t = "ahbgdc"
结果:循环条件不满足,直接返回 i === s.length 为 true(空字符串是任何字符串的子序列)