leetcode30:串联所有单词的子串

题目

给定一个字符串 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”]
输出:[]

思路:
  我开始的想法是先把words里的单词全排列,然后在s里找。。。。这样也行,但是太慢了。。。。。
  后来看了评论的题解,运用了滑动窗口和哈希表来解题。
  滑动窗口的大小就是words中所有单词的长度。一次滑动一格,依次判断滑动窗口里的字符串是否符合要求。
  如何确定滑动窗口内的字符串是由words里的字符串排列组成的呢?这个时候就要用到哈希表。
words建立哈希表,键是字符串,值是字符串在words中出现的次数。给滑动窗口里的字符串也建立哈希表;如果和words上的哈希表一样,说明此时的字符串符合要求。
代码:

class Solution(object):
    def findSubstring(self, s, words):
        """
        :type s: str
        :type words: List[str]
        :rtype: List[int]
        """
        if not s or not words:
            return []
        from collections import Counter
        aim = []
        l = len(words[0])
        length = l*len(words)
        Cwords = Counter(words)

        for i in range(len(s)):
            if i+length > len(s):
                break
            temp = s[i:i+length]
            array = []
            for j in range(len(words)):
                array.append(temp[j*l:(j+1)*l])
            array = Counter(array)
            if array == Cwords:
                aim.append(i)
        return aim

顺便记录一下两种全排列的算法:
第一种是两两交换:

aim = []
def Perm(array, m, n):
    if m==n:
        temp = copy.copy(array)
        aim.append(temp)
        return
    else:
        i = m
        while i<n:
            array[m], array[i] = array[i], array[m]
            Perm(array, m+1, n)
            array[m], array[i] = array[i], array[m]
            i +=1

第二种类似深搜,建立一颗树:

aim = []
#array是待排列的字符串;result存结果,初始化为空。
#每次递归都往result加一个字符
def Permut(array, result):
    if not array:
        aim.append(result)
        return
    for i in range(len(array)):

        temp = copy.copy(result)
        temp.append(array[i])

        temp1 = copy.copy(array)
        temp1.remove(array[i])

        Permut(temp1, temp)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值