Add min-window-substring using sliding window

This commit is contained in:
mbinary 2019-05-26 21:43:30 +08:00
parent 936d05bb32
commit 247df5fb71
2 changed files with 118 additions and 0 deletions

View File

@ -0,0 +1,58 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : insert_remove_getRandom.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.xyz
# Github: https://github.com/mbinary
# Created Time: 2019-05-24 10:01
# Description:
insert, remove, getRandom 的摊还时间为 O(1),
且有重复数据, remove 一次删除一个元素
#######################################################################
'''
class RandomizedCollection:
def __init__(self):
self.vals=[]
self.index={}
def insert(self, val: int) -> bool:
self.vals.append(val)
if val in self.index:
self.index[val].add(len(self.vals)-1)
return False
else:
self.index[val] = {len(self.vals)-1}
return True
def removeAll(self, val: int) -> bool:
if val not in self.index:
return False
begin = end = len(self.vals)-len(self.index[val])
for idx in self.index.pop(val):
if idx<begin:
while self.vals[end]==val:
end+=1
self.vals[idx]=self.vals[end]
self.index[self.vals[idx]].remove(end)
self.index[self.vals[idx]].add(idx)
self.vals = self.vals[:begin]
return True
def remove(self,val):
if val not in self.index:
return False
last = len(self.vals)-1
idx = self.index[val].pop()
if len(self.index[val])==0:
del self.index[val]
if idx!=last:
self.vals[idx] = self.vals[last]
self.index[self.vals[idx]].remove(last)
self.index[self.vals[idx]].add(idx)
self.vals.pop()
return True
def getRandom(self) -> int:
if self.vals:
return self.vals[random.randint(0,len(self.vals)-1)]

View File

@ -0,0 +1,60 @@
#coding: utf-8
''' mbinary
#######################################################################
# File : min-window-substring.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
# Blog: https://mbinary.xyz
# Github: https://github.com/mbinary
# Created Time: 2019-05-26 21:39
# Description:
from leetcode-cn #76: https://leetcode-cn.com/problems/minimum-window-substring/
给定一个字符串 S 和一个字符串 T请在 S 中找出包含 T 所有字母的最小子串
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明
如果 S 中不存这样的子串则返回空字符串 ""
如果 S 中存在这样的子串我们保证它是唯一的答案
since you have to find the minimum window in S which has all the characters from T, you need to expand and contract the window using the two pointers and keep checking the window for all the characters. This approach is also called Sliding Window Approach.
L ------------------------ R , Suppose this is the window that contains all characters of T
L----------------- R , this is the contracted window. We found a smaller window that still contains all the characters in T
When the window is no longer valid, start expanding again using the right pointer.
#######################################################################
'''
from collections import defaultdict
class Solution:
def minWindow(self, s: str, t: str) -> str:
def expand(j,lacked,dic):
while j<n and lacked:
if s[j] in lacked:
lacked[s[j]]-=1
if lacked[s[j]]==0:
del lacked[s[j]]
dic[s[j]]+=1
j+=1
return j
def contract(left,right):
for i in range(left,right):
dic[s[i]]-=1
if dic[s[i]]==0:
del dic[s[i]]
if s[i] in chars and (s[i] not in dic or dic[s[i]]<chars[s[i]]):
return i+1,{s[i]:1}
n ,i, j= len(s),0,0
ans = ''
dic,lacked = defaultdict(int), defaultdict(int)
for c in t:
lacked[c]+=1
chars = lacked.copy()
while j<n and lacked:
j = expand(j,lacked,dic)
if not lacked:
i,lacked=contract(i,j)
if ans=='' or len(ans)>j-i+1:
ans = s[i-1:j]
return ans