35.判断子序列(简单)

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

你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

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

示例 1:
s = “abc”, t = “ahbgdc”

返回 true.

示例 2:
s = “axc”, t = “ahbgdc”

返回 false.

后续挑战 :

如果有大量输入的 S,称作S1, S2, … , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

双指针法:

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        '''双指针法'''
        i = 0
        j = 0
        while i < len(s) and j < len(t):
            if s[i] == t[j]:
                i += 1
                j += 1
            else:
                j += 1
        if i == len(s):
            return True
        else:
            return False

生成器迭代器法:

生成器迭代器方法的思路:

t = iter(t) , 把列表 t 转化成了一个迭代器
(i for i in s) 产生一个生成器, 这个生成器可以遍历对象 s。
(i in t)可以联想到 for in 语句。

(i in t) , 大致等价于

while True:
    val = next(t)
    if val == i:
        yield True

巧妙地利用了成器的特性, next() 函数运行的时候, 保存了当前的指针。

那么((i in t) for i in s)可以理解为:遍历s中元素 i,并在t中查找元素 i 是否存在。
由于next() 函数和yield 生成器的特性,如果 t 存在 i 返回True并保存当前指针不存在返回False
(下一次查找从保存的指针开始继续查找,直到s 或者 t 遍历结束),这些True或False产生一个迭代器。

最后的 all() 函数,判断一个迭代器的元素是否全部为 True, 如果是则返回 True, 否则就返回 False。

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        '''生成器迭代器法'''
        t = iter(t)
        return all(((i in t) for i in s))

后续挑战:

后续挑战的思路:

  1. 用哈希集合hase_set记录下t中每个字符出现过的位置,即最多有26个key
  2. 对s中每个字母进行匹配,s[i]一定出现在s[i-1]之后,所以匹配s[i]的时候,应该找hash_set[s[i]]中大于s[i-1]的索引的索引值
  3. 我们用匹配左边界的二分法(即匹配第一个大于等于目标值的数),找当前字母索引列表中第一个大于上一个字母索引的值
  4. 如果某个匹配到的边界值等于当前字幕索引列表的长度,则表明无法匹配当前字母,返回False
    全部成功匹配返回True
class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        '''后续挑战'''
        hash_set = {}
        for i, word in enumerate(t):
            if word not in hash_set:
                hash_set[word] = [i]
            else:
                hash_set[word].append(i)
        # 匹配
        index = -1
        for word in s:
            if word not in hash_set:
                return False
            # 字母s出现的索引 用二分法找到其中大于index的第一个
            indexes = hash_set[word]
            left = 0
            right = len(indexes)
            while left < right:
                mid = left + (right - left) // 2
                if indexes[mid] > index:
                    right = mid
                else:
                    left = mid + 1
            if left == len(indexes):
                return False
            index = indexes[left]
            
        return True

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值