持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
题目
给定字符串 s
和 t
,判断 s
是否为 t
的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"
是 "abcde"
的一个子序列,而 "aec"
不是)。
示例 1:
- 输入:
s = "abc", t = "ahbgdc"
- 输出:
true
示例 2:
- 输入:
s = "axc", t = "ahbgdc"
- 输出:
false
方法一:双指针
思路及解法
本题询问的是, 是否是 的子序列,因此只要能找到任意一种 在 中出现的方式,即可认为 是 的子序列。
而当我们从前往后匹配,可以发现每次贪心地匹配靠前的字符是最优决策。
假定当前需要匹配字符 ,而字符 在 中的位置 和 出现,那么贪心取 是最优解,因为 后面能取到的字符, 也都能取到,并且通过 与 之间的可选字符,更有希望能匹配成功。
这样,我们初始化两个指针 和 ,分别指向 和 的初始位置。每次贪心地匹配,匹配成功则 和 同时右移,匹配 的下一个位置,匹配失败则 右移, 不变,尝试用 的下一个字符匹配 。
最终如果 移动到 的末尾,就说明 是 的子序列。
代码
class Solution {
func isSubsequence(_ s: String, _ t: String) -> Bool {
let sArray: [Character] = Array(s)
let tArray: [Character] = Array(t)
let n: Int = s.count
let m: Int = t.count
var i: Int = 0
var j: Int = 0
while i < n && j < m {
if sArray[i] == tArray[j] {
i += 1
}
j += 1
}
return i == n
}
}
复杂度分析
-
时间复杂度:,其中 为 的长度, 为 的长度。每次无论是匹配成功还是失败,都有至少一个指针发生右移,两指针能够位移的总距离为 。
-
空间复杂度:。