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))

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章