Skip to content

Latest commit

 

History

History
185 lines (133 loc) · 5.42 KB

0392._is_subsequence.md

File metadata and controls

185 lines (133 loc) · 5.42 KB

392. Is Subsequence

难度: Medium

刷题内容

原题连接

内容描述


Given a string s and a string t, check if s is subsequence of t.

You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100).

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not).

Example 1:
s = "abc", t = "ahbgdc"

Return true.

Example 2:
s = "axc", t = "ahbgdc"

Return false.

Follow up:
If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?

解题方案

思路 1 - 时间复杂度: O(len(s)+len(t))- 空间复杂度: O(1)******

最naive的思路是递归,原来可以beats 53.74%

但是今天上来发现多了case,超时过不了了

时间复杂度为O(len(s)+len(t))

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if s == '': 
            return True
        for i in range(len(t)):
        	if t[i] == s[0]:
        		return self.isSubsequence(s[1:],t[i+1:])

        return False

思路 2 - 时间复杂度: O(max(len(s), len(t)))- 空间复杂度: O(1)******

因为递归操作以及对字符串的操作太过于昂贵,所以用index来处理,节省了时间和空间

时间复杂度是O(max(len(s), len(t)))

beats 40%

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if s == '': 
            return True
        ps, pt = 0, 0
        while ps < len(s) and pt < len(t):
            if s[ps] == t[pt]:
                ps += 1
            pt += 1
        return ps >= len(s)

思路 3 - 时间复杂度: O(len(t))- 空间复杂度: O(1)******

想到说对于每一个s中的字符,看看在不在,找到了就记录一下t的当前位置idx,下次从t的idx+1后面开始找

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        idx = 0
        for c in s:
            idx = t.find(c, idx)
            if idx == -1:
                return False
            idx += 1
        return True

follow up question

If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?

思路 1 - 时间复杂度: O(lt+kmsO(lg(lt)))- 空间复杂度: O(lt)****

我们可以先把t里面的所有字符和其出现的idx的list分别作为key和value放进一个字典里面

然后对于s中的每个字符,我们要做两步判断:

  1. 如果这个字符不在字典里面,直接返回False
  2. 如果这个字符在字典里面,那我们就看看我们在这个字符在t里面出现的idx的list里面是不是有比上一个字符的idx更大的idx,

例如对于输入

"abc"
"ahbgdc"
首先初始化idx为-1
lookup = {'a': [0], 'c': [5], 'b': [2], 'd': [4], 'g': [3], 'h': [1]}
我们先找字符a,发现a在lookup里面的list为[0],并且里面存在比idx -1更大的元素,所以我们找到了字符a,更新 idx为1,意味着下一个字符要从t的idx 1开始找
开始找字符b,发现b在lookup里面的list为[2],并且里面存在比idx 1更大的元素,所以我们找到了字符b,更新idx 为3,意味着下一个字符要从t的idx 3开始找
开始找字符c,发现c在lookup里面的list为[5],并且里面存在比idx 3更大的元素,所以我们找到了字符c,更新idx 为6,意味着下一个字符要从t的idx 6开始找

但是此时所有字符都已经找到,直接返回True

假设t的长度为lt,s的长度为ls,一共有k个s(假设最长的一个s长度为ms)

我们只需要最开始对整个t做一个遍历,时间复杂度为O(lt),同时用了一个字典,空间复杂度为O(lt),

然后对于每一个s的每一个字符,我们都只需要进行一个二分查找,时间复杂度为O(lg(lt)),因为最坏有可能t只有一个字符,它在字典里面对应的list的长度就是lt

因此最终的时间复杂度为O(lt+kmsO(lg(lt))),时间复杂度为O(lt)

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        lookup = {}
        for i in range(len(t)):
            if t[i] in lookup:
                lookup[t[i]].append(i)
            else:
                lookup[t[i]] = [i]
        idx = -1
        for c in s:
            if c not in lookup:
                return False
            else:
                c_idx = bisect.bisect_left(lookup[c], idx)
                if c_idx == len(lookup[c]): # this means we don't find next char of s in t
                    return False
                idx = lookup[c][c_idx] + 1 # we have to find next char from the prev char's index + 1
        return True