Swift - LeetCode - 判断子序列

1,663 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

题目

给定字符串 st,判断 s 是否为 t 的子序列。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace""abcde" 的一个子序列,而 "aec" 不是)。

示例 1:

  • 输入: s = "abc", t = "ahbgdc"
  • 输出: true

示例 2:

  • 输入: s = "axc", t = "ahbgdc"
  • 输出: false

方法一:双指针

思路及解法

本题询问的是,ss 是否是 tt 的子序列,因此只要能找到任意一种 sstt 中出现的方式,即可认为 sstt 的子序列。

而当我们从前往后匹配,可以发现每次贪心地匹配靠前的字符是最优决策。

假定当前需要匹配字符 cc,而字符 cctt 中的位置 x1x_1x2x_2 出现x1<x2(x_1 < x_2),那么贪心取 x1x_1 是最优解,因为 x2x_2 后面能取到的字符,x1x_1 也都能取到,并且通过 x1x_1x2x_2 之间的可选字符,更有希望能匹配成功。

这样,我们初始化两个指针 iijj,分别指向 sstt 的初始位置。每次贪心地匹配,匹配成功则 iijj 同时右移,匹配 ss 的下一个位置,匹配失败则 jj 右移,ii 不变,尝试用 tt 的下一个字符匹配 ss

最终如果 ii 移动到 ss 的末尾,就说明 sstt 的子序列。

代码

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
    }
}

复杂度分析

  • 时间复杂度:O(n+m)O(n+m),其中 nnss 的长度,mmtt 的长度。每次无论是匹配成功还是失败,都有至少一个指针发生右移,两指针能够位移的总距离为 n+mn+m

  • 空间复杂度:O(1)O(1)