您的位置:首页 > 其它

leetcode -- Minimum Window Substring -- 重点,应该会考

2015-12-22 21:31 531 查看
https://leetcode.com/problems/minimum-window-substring/

思路:

与Minimum Subarray Sum题目很像,/article/8637594.html

用的trick一样。

解题思路:双指针思想,尾指针不断往后扫,当扫到有一个窗口包含了所有T的字符,然后再收缩头指针,直到不能再收缩为止。最后记录所有可能的情况中窗口最小的。

先找到一个window包括所有T的字母,找到window end, 这个时候只是window包括所有的字母,接下来我们就要收缩window的start,直到这个window依然还包括所有的字母。这个时候的start到end就是一个候选的最佳区间,然后end继续往前走,每走一步,都要试图去收缩start,start到end区间会一直包括所有T里面的字母,直到end到末尾

结合最终的code(只用count1,不用count2)来分析,在找第一个window的过程中,count1会因为S中某些字母重复而变成负数,例如S = [AAABAAACAB], T = [ABC], 所以在收缩start的时候,只要S[start]对应的count1小于0,那么就count1[S[start]] += 1,因为只要start继续往前,start:end+1区间肯定还有S[start]出现,但是如果S[start]对应的count1等于0,那么就不能继续往前了,因为继续往前的话,S[start]不会再次出现。这样我们就得到了第一个window的start和end。此时count == 0了,并且接下来一直为0。即,end继续往前走,每走一步,都要试图去收缩start,直到end到末尾。

思路很好理解,复习的时候再做一下。code看不太懂

参考:/article/4981655.html

http://randombet.blogspot.hk/2014/09/leetcode-minimum-window-substring-python.html

Ref中的code

可以AC,但是不好理解,其实可以简化code,见下面的note

class Solution(object):
def minWindow(self, S, T):
"""
:type s: str
:type t: str
:rtype: str
"""
count1={}; count2={}
for char in T:#count1记录T中字母的个数
if char not in count1: count1[char]=1
else: count1[char]+=1
for char in T:#count2只负责记录s中某个字母是否是T中的字母。
if char not in count2: count2[char]=1
else: count2[char]+=1
count=len(T)
start=0; minSize=100000; minStart=0
for end in range(len(S)):
if S[end] in count2:
count1[S[end]]-=1
if count1[S[end]]>=0:
count-=1

if count==0:
while True:#一直到count1没有负的。
if S[start] in count2:
if count1[S[start]]<0:
count1[S[start]]+=1
else:#count1对应元素为0.那么start就不能再往前走了,否则这个元素就不包括在start:end的区间内了。count1没有负的.没有多余的T中的元素,即[start: end + 1]这个range就是最小的range之一。
break
start+=1
if minSize>end-start+1:
minSize=end-start+1; minStart=start
#break
if minSize==100000: return ''
else:
return S[minStart:minStart+minSize]


note1

这里做了个test,发现找到第一个window之后,count == 0,之后count就一直是0,并且是end每往前走一步,都会试图收缩start。下面用flag作为count是否已经被置为0的标记,如果已经被置为0,以后就等价于去掉if count == 0这个条件。

class Solution(object):
def minWindow(self, S, T):
"""
:type s: str
:type t: str
:rtype: str
"""
count1={}; count2={}
for char in T:#count1记录T中字母的个数
if char not in count1: count1[char]=1
else: count1[char]+=1
for char in T:#count2只负责记录s中某个字母是否是T中的字母。
if char not in count2: count2[char]=1
else: count2[char]+=1
count=len(T)
start=0; minSize=100000; minStart=0
flag = False
for end in range(len(S)):
if S[end] in count2:
count1[S[end]]-=1
if count1[S[end]]>=0:
count-=1
if not flag:
if count==0:
while True:#一直到count1没有负的。
if S[start] in count2:
if count1[S[start]]<0:
count1[S[start]]+=1
else:#count1对应元素为0.那么start就不能再往前走了,否则这个元素就不包括在start:end的区间内了。count1没有负的.没有多余的T中的元素,即[start: end + 1]这个range就是最小的range之一。
break
start+=1
if minSize>end-start+1:
minSize=end-start+1; minStart=start
flag = True
else:
while True:#一直到count1没有负的。
if S[start] in count2:
if count1[S[start]]<0:
count1[S[start]]+=1
else:#count1对应元素为0.那么start就不能再往前走了,否则这个元素就不包括在start:end的区间内了。count1没有负的.没有多余的T中的元素,即[start: end + 1]这个range就是最小的range之一。
break
start+=1
if minSize>end-start+1:
minSize=end-start+1; minStart=start

if minSize==100000: return ''
else:
return S[minStart:minStart+minSize]


note2,最终code

这里还发现count2其实就只是记录s中的某个字母是否是T中的字母。这里其实只需要count1。

class Solution(object):
def minWindow(self, S, T):
"""
:type s: str
:type t: str
:rtype: str
"""
count1={}
for char in T:#count1记录T中字母的个数
if char not in count1: count1[char]=1
else: count1[char]+=1
count=len(T)
start=0; minSize=100000; minStart=0
for end in range(len(S)):
if S[end] in count1:
count1[S[end]]-=1
if count1[S[end]]>=0:
count-=1
if count==0:#找到了第一个window的end
while True:#一直到S[start]对应的count1是0,即没有重复过。就找到了window的start
if S[start] in count1:
if count1[S[start]]<0:#说明这个字母重复过,start继续往前的走的话,还有这个字母在后头
count1[S[start]]+=1
else:#count1对应元素为0.那么start就不能再往前走了,否则这个元素就不包括在start:end的区间内了。count1没有负的.没有多余的T中的元素,即[start: end + 1]这个range就是最小的range之一。
break
start+=1
if minSize>end-start+1:
minSize=end-start+1; minStart=start

if minSize==100000: return ''
else:
return S[minStart:minStart+minSize]


自己重写code

有bug的code

class Solution(object):
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
count1 = {}
for x in t:
if x in count1:
count1[x] += 1
else:
count1[x] = 1
count = len(count1)
i, j = 0, 0
minwin = len(s)
min_i, min_j = len(s) - 1, 0
while i < len(s):

if s[i] in count1:
count1[s[i]] -= 1
if count1[s[i]] == 0:
count -= 1

if count == 0:

while j <= i:

if s[j] in count1:
if count1[s[j]] < 0:
count1[s[j]] += 1
if count1[s[j]] == 0:#这里要改成elif
break
j += 1
if i - j + 1 < minwin:
minwin = i - j + 1
min_i = i
min_j = j
i += 1
if count == 0:
return s[min_j: min_i + 1]
else:
return ''


通过的code

class Solution(object):
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
count1 = {}
for x in t:
if x in count1:
count1[x] += 1
else:
count1[x] = 1
count = len(count1)
i, j = 0, 0
minwin = len(s)
min_i, min_j = len(s) - 1, 0
while i < len(s):

if s[i] in count1:
count1[s[i]] -= 1
if count1[s[i]] == 0:#这里可以是==0, count = len(count1). 或者跟ref一样
count -= 1

if count == 0:
while j <= i:#这里有等号跟没等号效果一样。

if s[j] in count1:
if count1[s[j]] < 0:
count1[s[j]] += 1
elif count1[s[j]] == 0:
#这里注意一定要是elif而不能是if,否则上面的if如果成立,可能可以又进入这一个if
break
j += 1
if i - j + 1 < minwin:
minwin = i - j + 1
min_i = i
min_j = j
i += 1
if count == 0:
return s[min_j: min_i + 1]
else:
return ''
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: