leetcode刷题笔记-substring题

76. Minimum Window Substring 

有模板的题!https://leetcode.com/problems/minimum-window-substring/discuss/26808/Here-is-a-10-line-template-that-can-solve-most-'substring'-problems

class Solution(object):
    def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        target_map = collections.Counter(t)
        count = len(t)
        begin = end = head = 0
        dis = sys.maxsize
        
        while end < len(s):
            if target_map[s[end]] > 0:
                count -= 1
            
            target_map[s[end]] -= 1  # aa
            end += 1
            
            # When we found a valid window, move start to find smaller window.
            while count == 0:
                if (end - begin) < dis:
                    dis = end - begin
                    head = begin
                
                target_map[s[begin]] += 1  # aa
                # When char exists in target, increase counter. 如果不是在t里面的,上面加回来最多回到0
                if target_map[s[begin]] > 0:
                    count += 1
                
                begin += 1
        
        return "" if dis == sys.maxsize else s[head:head + dis]

727. Minimum Window Subsequence

定义dp[i][j]表示S的前缀S[0,i]中的起始索引k,使得T[0,j]是S[k,i]的子串。这样如果S[i] == T[0],则dp[i][0] = i,否则dp[i][0] = -1。而递推公式为:如果S[i] == T[j],那么dp[i][j] = max(dp[k][j-1]), 0 <= k < i。否则dp[i][j] = -1。而我们的目标则是找到min(i - dp[i][n-1]),其中n是T的长度。

class Solution(object):
    def minWindow(self, S, T):
        s, t = len(S), len(T)
        dp = [[-1]*(t) for _ in xrange(s)]
        
        # if S[i] ==  T[0] dp[i][0] = i  
        for i in xrange(s):
            if S[i] == T[0]:
                dp[i][0] = i
        for j in xrange(1, t):
            k = -1
            for i in xrange(0, s):
                # if S[i] == T[j], dp[i][j] = max(dp[k][j-1]) where 0<= k < i
                if k != -1 and S[i] == T[j]:
                    dp[i][j] = k
                if dp[i][j-1] != -1:
                    k = dp[i][j-1]
        length = float('inf') 
        startIdx = -1
        for i in xrange(s):
            if dp[i][t-1] != -1 and i - dp[i][t-1] + 1 < length :
                length = i - dp[i][t-1] + 1
                startIdx = dp[i][t-1]
        return S[startIdx: startIdx+length] if length != float('inf') else ""

two point beat 100%的方法:

第一个for 先保证T 一定在S里面,第二个for循环就是找最rightmost的T[0]

class Solution:
    def minWindow(self, S, T):
        res = ""
        start = -1
        while True:
            first = start + 1
            for c in T:
                start = S.find(c, start + 1)
                if start == -1:
                    return res
            
            start = end = start + 1
            for c in reversed(T):
                start = S.rfind(c, first, start)
            
            if res == "" or len(res) > end - start:
                res = S[start:end]

159. Longest Substring with At Most Two Distinct Characters

模板题

 

class Solution(object):
    def lengthOfLongestSubstringTwoDistinct(self, s):
        """
        :type s: str
        :rtype: int
        """
        
        count = begin = end = dis = 0
        window = collections.defaultdict(int)
        while end < len(s):
            if window[s[end]] == 0:
                count += 1  # 有几个不同的字母在window里面了
            window[s[end]] += 1  # 把右边字母加到window
            end += 1
            
            while count > 2:  # 滑动窗口让count == 2
                window[s[begin]] -= 1  # 减掉左边的字母
                if window[s[begin]] == 0:
                    count -= 1
                begin += 1
            
            dis = max(dis, end-begin)
            
        return dis

340. Longest Substring with At Most K Distinct Characters

最长有效子串的模板题

 

class Solution(object):
    def lengthOfLongestSubstringKDistinct(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: int
        """
        
        begin = end = dis = count = 0
        window_map = collections.defaultdict(int)
        
        while end < len(s):
            if window_map[s[end]] == 0:
                count += 1
            window_map[s[end]] += 1
            end += 1
            
            while count > k:
                window_map[s[begin]] -= 1
                if window_map[s[begin]] == 0:
                    count -= 1
                begin += 1
            
            dis = max(dis, end-begin)
            
        return dis

395. Longest Substring with At Least K Repeating Characters

思路:没想到是分治法之前,一直做不出来。看到可以用分治法后就很容易。

要找s[i,j]的最大子串,先统计频数,然后遍历一遍频数,找出第一个频数小于k且大于0的字符,然后找出这个字符的位置,接下来的分析很重要,这个字符一定不能出现在任何的子串中,因为i,j是整个的子串,在ij里面频数都没有达到k,那么在ij的任何子串中,这个字符也不可能达到频数k。所以不能有这个字符,那么就在这个位置做一个分治,返回前半部分和后半部分的最大值。 

class Solution(object):
    def longestSubstring(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: int
        """
        return self.divide(0, len(s), s, k)

    def divide(self, start, end, s, k):

        if end > len(s) or end <= 0:
            return 0
        dic = collections.defaultdict(int)
        check = set()
        for i in xrange(start, end):
            dic[s[i]] += 1
        
        for i in xrange(start, end):
            if dic[s[i]] < k:
                check.add(i)
                break
        
        if not check:
            return end - start
        else:
            ids = check.pop()
            return max(self.divide(start, ids, s, k), self.divide(ids + 1, end, s, k))

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值