76. 最小覆盖子串
难度:困难
问题描述:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:·
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
示例 2:
输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
问题描述简单,但实际难度不小,含金量很高,我解决之后还没有感觉到什么,不过后来看到有人说这是各大IT企业招考的热题,而且很多都栽在了这道题上,才晓得不一般了。
我的思路是这样的:
- 先把s串中凡是t中的字符其索引号取出,存于a列表中
- 其次把s串中凡是t中的字符按顺序取出,单独存于s1字符串中,a列表中的索引号元素顺序和s1串中的字符顺序具有对应关系,方便查找,同时用s1来处理最小子串比用原s串要容易得多
- 在s1中循环查找包含t串的所有子串并存于b列表中,记录其在s1中的索引号起止位置和在原s中的长度,因为要得到在s中的最小长度子串
- 将b列表中所有子串按子串长度是不是最小值进行过滤,得到过滤之后的子串列表y,然后将重复项去掉,得到简化的最小子串列表c
- 最后将列表c中的数据项按其意义翻译成最小子串组合输出即得到问题的求解
程序如下:
'''
函数checksub(s,t)用于判断字符串s中是否包含t中所有字符
如果是,返回True,否则返回False
'''
def checksub(s,t):
for char in t:
if char in s:
continue
else:
return False
else:
return True
#输入字符串s和t
s=input('pls input s=')
t=input('pls input t=')
'''
将字符串s中所有含有t字符串中
字符的索引号取出并存入a列表中
'''
a=[]
for i in range(len(s)):
if s[i] in t:
a.append(i)
print('含t中字符的索引号列表:',a)
#生成从原字符串s中取出t中字符组成的字符串s1
s1=''.join(map(lambda i:s[i],a))
print('按顺序从s中取出t中字符组成的字符串:',s1)
'''在s1字符串中找到各种含有t中字符的所有子串,
并将其在s1中的索引号和这个子串在原s中的长
度以[[索引号1,索引号2],长度]的形式保存在b列表中
'''
b=[]
for i in range(len(s1)):
k=i
for j in range(i+1,len(s1)+1):
c=s1[k:j]
if checksub(c,t):
b.append([[k,j-1],a[j-1]-a[k]+1])
k=j-1
#在b中将各种组合中长度最小的找出生成y列表,然后合并,去掉重复的,得到最小组合c
y=list(x for x in b if x[1]==min(x[1] for x in b))
c=[]
for i in y:
if i in c:
continue
else:
c.append(i)
print('各种可能的最小组合列表:',c)
'''
将c中各种组合取出,即为本问题的解答
因为s1串和a列表具有对应关系,所以知道s1中字符的索引号就可以查到a中数据的对应索引号,而a中数据本身是一个索引号,这样就可以查到其在原s串中的位置从而取出对应字符,有点类似间址寻址的意思
'''
if len(c)==0:
print('""')
else:
for i in c:
x=a[i[0][0]]
y=a[i[0][1]]
ms=s[x:y+1]
if len(ms)<len(t):
print('""')
else:
print('组合在原列表s中的索引号为:',x,y)
print('"'+ms+'"')
运行实例一:
pls input s=ADOBECODEBANC
pls input t=ABC
含t中字符的索引号列表: [0, 3, 5, 9, 10, 12]
s中取出t中字符组成的字符串: ABCBAC
各种可能的最小组合列表: [[[3, 5], 4]]
组合在原列表s中的索引号为: 9 12
"BANC"
运行实例二:
pls input s=a
pls input t=aa
含t中字符的索引号列表: [0]
s中取出t中字符组成的字符串: a
各种可能的最小组合列表: [[[0, 0], 1]]
""
运行实例三:
pls input s=a
pls input t=b
含t中字符的索引号列表: []
s中取出t中字符组成的字符串:
各种可能的最小组合列表: []
""