Leetcode_30【串联所有单词的子串】

文章目录:

  • 题目
  • 脚本一
  • 脚本一逻辑
  • 脚本二
  • 脚本二逻辑

题目:

给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例 1:

输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:

输入:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
输出:[]


脚本一:【用时:2300ms】

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        try:
            leng1 = len(words[0])
        except IndexError:
            return([])
        leng1 = len(words[0])
        leng2 = len(s)
        leng3 = len(words)
        leng4 = words.count(words[0])
        num1 = leng1 * leng3
        try:
            str_1 = s[0] * leng2
        except IndexError:
            return([])
        list1 = words[:]
        list2 = []
        flag1,flag2,flag3 = 1,1,1
        if str_1 == s:
            flag1 = 0
        if leng3 == leng4:
            flag2 = 0
        if words[0] in s:
            flag3 = 0
        if flag1 == 0 and flag2 == 0 and flag3 == 0:
            result = leng2 - num1 + 1
            list2 = list(range(result))
            return(list2)
        i = 0
        k = 0
        while True:
            j = i + leng1
            str1 = s[i:j]
            if str1 in list1:
                list1.remove(str1)
                i += leng1
                if not list1:
                    list2.append(k)
                    k += 1
                    i = k
                    list1 = words[:]
            else:
                k += 1
                i = k
                list1 = words[:]
            if i > leng2:
                return(list2)

脚本一逻辑:

  • 此题是笔者想到的解法,可以规类为暴力破解,原脚本是超时的;但笔者根据leetcode的超时反馈,做了一些调优
  • 脚本的基本逻辑如下:
    • 比如长字符串str为abbcc,words组合为[aa,bb]
    • 第一步:先在长字符串str获取长度为2的短字符串str1为"ab"(aa的长度为2),由于"ab"不在words中,所以长字符串获取点由0加1变为1
    • 第二步:再获取长度为2的短字符串bb,由于bb在words中,则剔除words中的该元素,则words变为[aa]
    • 第三步:再获取长度为2的短字符串aa,由于aa在words中,则剔除words中的此元素,则words变为[]
    • 第四步:如果words变为空,则返回最新开始的取点位,如本例中的1,并将1添加到空列表中
    • 重复

脚本二:【用时:870ms 转载】

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        res = []
        write = []
        if len(words) == 0:
            return []
        if len(s) < len(words)*len(words[0]):
            return []
        dic = {}
        flag = 0
        for i in words:
            try:
                dic[i]+=1
            except KeyError:
                dic[i]=1
                flag+=1
                write.append(i)
        #是否存在用字典查看
        left, right = 0, len(words)*len(words[0])
        #滑动窗口
        while right<=len(s):
            n,start = 0,left
            per = len(words[0])
            tag = dict(zip(write,[0]*flag))
            while n < len(words):
                #若存在于字典中
                if dic.get(s[start:start+per]):
                    if tag[s[start:start+per]] < dic[s[start:start+per]]:
                        tag[s[start:start+per]] += 1
                        n+=1
                        start+=per
                    else:
                        break
                else:
                    break
            if n == len(words):
                res.append(left)
            left+=1
            right+=1
        return res

        

脚本二逻辑:

  • 第一:对明显不符合的情况进行排除,比如子串列表为空,或者子串总长度比字符串s还要长
  • 第二:创建两个字典dic、tag和一个列表res,其中dic记录子串列表words中的信息,words中每个元素作为字典的键,元素个数作为字典的值;每次进行最外层循环时,tag循环都会恢复原样,原样为已words列表作为字典的键,以0作为值 
  • 第三:每次进行主循环时,以长字符串的某个字符为起点,进入次循环;若次循环中满足条件则记录结果的空列表增加起点字符的索引值后,起点索引值自增1,进入主循环;若次循环条件不满足,则起点索引值自增1并再次进入主循环;直到未遍历的长字符串字符数小于words所有元素总长度

猜你喜欢

转载自www.cnblogs.com/mailong/p/12046508.html