[LeetCode]Is Subsequence

392. Is Subsequence

这道题目可以使用很多种解法,包括是动态规划等等。

动态规划

s为匹配字符串,t为给定字符串假设dp[i][j]表示t从开始到第i个字符时对应s从开头到第j个字符,s所否是t的子序列。

分析:在比较的过程中,如果t[i]不等于s[j],则忽略掉当前的字符,取之前i-1匹配的情况,如果是相等,则取决于双方上一位的匹配的情况,这里注意的是,如果匹配字符串为空,那么结果为True。

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if not s and not t:
            return True
        elif not s and t:
            return True
        elif not t and s:
            return False
        m, n = len(t), len(s)
        dp = [[False for i in range(n + 1)] for j in range(m + 1)]
        dp[0][0] = True
        for i in range(1, m + 1):
            dp[i][0] = True
        for i in range(1, n + 1):
            dp[0][i] = False
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                if t[i-1] == s[j-1]:
                    dp[i][j] = dp[i - 1][j - 1]
                else:
                    dp[i][j] = dp[i - 1][j]
        return dp[m][n]

但因为空间的复杂度过大导致了TLE,所以需要再进一步的进行优化,因为我们只使用到了上一行的状态,因此我们可以只使用两行,然后使用完的时候进行交换即可。

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if not s and not t:
            return True
        elif not s and t:
            return True
        elif not t and s:
            return False
        m, n = len(t), len(s)
        dp = [[False for j in range(m + 1)] for i in range(2)]
        for i in range(m + 1):
            dp[0][i] = True
        for i in xrange(1, n+1):
            for j in xrange(1, m+1):
                if s[i-1] == t[j-1]:
                    dp[1][j] = dp[0][j-1]
                else:
                    dp[1][j] = dp[1][j-1]
            dp[0] = dp[1][:]
        return dp[1][m]

但是,依旧是TLE,我们继续在它的基础之上进行优化,因为只有在不相等的情况的时候才会使用到上一行的状态,而且只用到了它的值,因此,我们使用一个变量来进行维护。

不会

二分搜索

一开始我看到这个方法的时候,居然傻傻的去对字符串进行搜索😳。

思路:纪录给定字符串每个字符对应的位置,维护前一个字符的位置,然后遍历匹配字符串去找到比前一个字符位置要大的位置,但是又不能超出数组长度,因为这样显然是因为前一个字符在不存在。

import collections
class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        def binary_search(nums, x):
            low, high = 0, len(nums)
            while low < high:
                mid = (low + high) // 2
                if nums[mid] < x:
                    low = mid + 1
                else:
                    high = mid
            return high
        if not s and not t:
            return True
        elif not s and t:
            return True
        elif not t and s:
            return False
        pre_idx = 0
        idxs = collections.defaultdict(list)
        for i,n in enumerate(t):
            idxs[n].append(i)
        for i in range(len(s)):
            idx = binary_search(idxs[s[i]], pre_idx)
            if idx != len(idxs[s[i]]):
                pre_idx = idxs[s[i]][idx] + 1
            else:
                return False
        return True

贪心

其实上面的做法也是贪心的思想,只要后者比前者大就更新,那这里就直接使用内建函数index

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if not s and not t:
            return True
        elif not s and t:
            return True
        elif not t and s:
            return False
        pre_idx = -1
        for i in range(len(s)):
            idx = t.find(s[i], pre_idx+1)
            if idx != -1:
                pre_idx = idx
            else:
                return False
        return True

滑动窗口

移动窗口本质也是贪心的思想,之前的动态规划时间复杂度为O(n^2),二分搜索优化到了O(nlogn),滑动窗口则直接优化到了O(n)。

思路:每当匹配字符串中的字符和给定字符串中的字符相等时,则移动匹配下标,其余均移动给定字符串下标,查看最后移动下标是否到达最后。

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if not s and not t:
            return True
        elif not s and t:
            return True
        elif not t and s:
            return False
        m, n = len(s), len(t)
        si, ti = 0, 0
        while si < m and ti < n:
            if s[si] == t[ti]:
                si += 1
            ti += 1
        return si == m
posted @ 2017-08-30 12:09  banananana  阅读(199)  评论(0编辑  收藏  举报