76. Minimum Window Substring
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))