利用类似间址寻址的原理解决LeetCode热题第76题最小覆盖子串

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企业招考的热题,而且很多都栽在了这道题上,才晓得不一般了。

我的思路是这样的:

  1. 先把s串中凡是t中的字符其索引号取出,存于a列表中
  2. 其次把s串中凡是t中的字符按顺序取出,单独存于s1字符串中,a列表中的索引号元素顺序和s1串中的字符顺序具有对应关系,方便查找,同时用s1来处理最小子串比用原s串要容易得多
  3. 在s1中循环查找包含t串的所有子串并存于b列表中,记录其在s1中的索引号起止位置和在原s中的长度,因为要得到在s中的最小长度子串
  4. 将b列表中所有子串按子串长度是不是最小值进行过滤,得到过滤之后的子串列表y,然后将重复项去掉,得到简化的最小子串列表c
  5. 最后将列表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中字符组成的字符串:

各种可能的最小组合列表: []

""

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值