LeetCode 727. Minimum Window Subsequence 双指针 NextMatch数组

231 篇文章 0 订阅

Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequence of W.

If there is no such window in S that covers all characters in T, return the empty string "". If there are multiple such minimum-length windows, return the one with the left-most starting index.

Example 1:

Input: 
S = "abcdebdde", T = "bde"
Output: "bcde"
Explanation: 
"bcde" is the answer because it occurs before "bdde" which has the same length.
"deb" is not a smaller window because the elements of T in the window must occur in order.

 

Note:

  • All the strings in the input will only contain lowercase letters.
  • The length of S will be in the range [1, 20000].
  • The length of T will be in the range [1, 100].

----------------------------------------------------------------------

非常好的一道题目。

双指针解法:双指针,把T覆盖以后,两个字符串的指针同时向前移,一直找到T耗尽为止。。。然后下一轮再从上次匹配到位置的下一个开始。

class Solution:
    def minWindow(self, S, T):
        slen,tlen,i,j = len(S),len(T),0,0
        maxL,res = slen+1,""
        while (i < slen):
            if (S[i] == T[j]):
                j += 1
                if (j == tlen):
                    j -= 1
                    end = i #bug1: end=j
                    while (j >= 0):
                        if (T[j] == S[i]):
                            j -= 1
                        i -= 1
                    i += 1
                    if (end-i+1 < maxL):
                        maxL = end-i+1
                        res = S[i:end+1]
            i += 1
        return res

BFS解法:被覆盖的字符串T中的第一个字符T[0]会匹配S中的某几个字符,如果把匹配到的这几个位置记下来。到了T[1],T[2]..T[n-1]依次往后推进之前的匹配位置,最终比一下最短那个,典型的BFS思路

class Solution(object):
    def minWindow(self, S, T):
        slen,tlen,c,n = len(S),len(T),0,1
        layers = [[(i,i) for i in range(slen) if S[i] == T[0]],[]] #(start,end)
        for i in range(1,tlen):
            tch = T[i]
            for first,last in layers[c]:
                tgt = S.find(tch, last+1)
                if (tgt != -1):
                    layers[n].append((first, tgt))
            if (not layers[n]):
                return ""
            layers[c].clear()
            c,n = n,c
        maxL,res = slen + 1,""
        for first, last in layers[c]:
            if (last-first+1 < maxL):
                maxL = last-first+1
                res = S[first:last+1]
        return res

NextMatch数组解法:其实就是把上述解法的S.find替换成O(1)的复杂度,和 https://blog.csdn.net/taoqick/article/details/106699543 这篇中求NextMatch的思路完全一样,而且这里的写法更简洁:

class Solution(object):
    def minWindow(self, S, T):
        slen,tlen,c,n = len(S),len(T),0,1
        nxt = [-1 for i in range(26)]
        nxt_arr = [None for i in range(slen)]

        for i in range(slen-1, -1, -1):
            ch_idx = ord(S[i])-ord('a')
            nxt[ch_idx] = i
            nxt_arr[i] = tuple(nxt)

        layers = [[(i,i) for i in range(slen) if S[i] == T[0]],[]] #(start,end)
        for i in range(1,tlen):
            tch = T[i]
            for first,last in layers[c]:
                #tgt = S.find(tch, last+1)
                tgt = nxt_arr[last+1][ord(tch)-ord('a')] if last+1<slen else -1
                if (tgt != -1):
                    layers[n].append((first, tgt))
            if (not layers[n]):
                return ""
            layers[c].clear()
            c,n = n,c
        maxL,res = slen + 1,""
        for first, last in layers[c]:
            if (last-first+1 < maxL):
                maxL = last-first+1
                res = S[first:last+1]
        return res

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值