2021-02-10

2021-02-10 Leetcode每日刷题

题目

给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。

示例1:

输入: s1 = “ab” s2 = “eidbaooo”
输出: True
解释: s2 包含 s1 的排列之一 (“ba”).

示例2:

输入: s1= “ab” s2 = “eidboaoo”
输出: False

我的思路
首先根据之前几天的题目知道这是一个滑动窗口题。我的想法是套用昨天的基本滑动窗口模板,用字典记录下窗口[left,right]内部每个字母出现的次数。当该字典与s1的字典相等时表示当前窗口内部是一个s1的排列。
另外需要考虑的情况包括当right指向的数不在s1内部时可以令left和right都指向下一个数,当窗口长度等于s1长度的时候是定长的滑动窗口,因此美移动一格right需要移动一格left,在移动left之前要把其指向的数字出现的次数-1,窗口长度-1。

class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        left = 0
        right = 0
        counter1 = collections.Counter()
        counter2 = collections.Counter()
        nums = 1
        for i in s1:
            counter1[i]+=1
        while right<len(s2):
            if s2[right] not in s1:
                right+=1
                left = right
                counter2 = collections.Counter()
                nums = 1
                continue
            counter2[s2[right]]+=1
            if counter1==counter2:
                return True
            if nums==len(s1):
                counter2[s2[left]]-=1
                if counter2[s2[left]] == 0:
                    counter2.pop(s2[left])
                left+=1
                nums-=1
                     
            right+=1
            nums+=1
        return False

提交结果:
2021-02-10_第1张图片
参考思路:
其实和这个思路差不多,但是从简化代码的角度来看不必要分这么多情况,直接用一个定长为len(s1)的滑动窗口放在s2中,right+1的同时left+1,判断内部的counter2是否等于counter1。

class Solution(object):
    def checkInclusion(self, s1, s2):
        """
        :type s1: str
        :type s2: str
        :rtype: bool
        """
        # 统计 s1 中每个字符出现的次数
        counter1 = collections.Counter(s1)
        N = len(s2)
        # 定义滑动窗口的范围是 [left, right],闭区间,长度与s1相等
        left = 0
        right = len(s1) - 1
        # 统计窗口s2[left, right - 1]内的元素出现的次数
        counter2 = collections.Counter(s2[0:right])
        while right < N:
            # 把 right 位置的元素放到 counter2 中
            counter2[s2[right]] += 1
            # 如果滑动窗口内各个元素出现的次数跟 s1 的元素出现次数完全一致,返回 True
            if counter1 == counter2:
                return True
            # 窗口向右移动前,把当前 left 位置的元素出现次数 - 1
            counter2[s2[left]] -= 1
            # 如果当前 left 位置的元素出现次数为 0, 需要从字典中删除,否则这个出现次数为 0 的元素会影响两 counter 之间的比较
            if counter2[s2[left]] == 0:
                del counter2[s2[left]]
            # 窗口向右移动
            left += 1
            right += 1
        return False

作者:fuxuemingzhu
链接:https://leetcode-cn.com/problems/permutation-in-string/solution/zhu-shi-chao-xiang-xi-de-hua-dong-chuang-rc7d/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

官方提供的两个思路也都很好,但是我记不住。有空补上。写作业去了。

你可能感兴趣的:(leetcode)