LeetCode-567-字符串的排列-滑动窗口
567、字符串的排列
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例1:
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").
示例2:
输入: s1= "ab" s2 = "eidboaoo"
输出: False
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-in-string
解题思路:
左右设置两个下标,左右下标围成一小块区域为窗口,在要匹配的字符串上进行从前往后的滑动,找到符合题意的子串
窗口初始化:左右下标初始为0
步骤:右下标一个一个往后移动,每当找到一个目标字符,就加入窗口中,直到窗口中包含所有要找的字符,当满足条件时,才移动左下标,来优化结果,缩小窗口,移动时要判断左下标右移后要删掉的那个元素是否是题目所需,如果是还要进行一系列操作,详细参见代码中的注释。
class Solution(object): def checkInclusion(self, s1, s2): windows = dict() needs = dict() for i in s1: if i in needs: needs[i] = needs[i] + 1 else: needs[i] = 1 right = left = 0 voiad = 0 while right < len(s2):#右下标不能超过字符串末尾 c = s2[right]#提取右下标指向的元素c right += 1#右下标右移一位 if c in needs:#如果c是需要的字符,则对字符进行操作,如果不是,直接下次循环,直到右下标指向有用的字符 if c in windows:#如果c曾找到过,曾放入过窗口中,则直接数量加1 windows[c] = windows[c] + 1 else:#如果c不曾找到过,窗口中还未曾加入过,则置窗口中该字符的数量为1,说明此刻找到了一个 windows[c] = 1 if windows[c] == needs[c]:#如果c这个字符的数量,和要求的c的数量相同,则说明c这个字符找够了,则将已找到的字母数+1 voiad += 1 while voiad == len(needs):#已找到的的字母数=要找的字符集的字母数,说明窗口中已经包含了所有要找的字母了(包括每个字母的不同个数),可以进行窗口的优化了 d = s2[left]#记下左下标所指的字符d left = left + 1#左下标右移一位 if right - left + 1 == len(s1):#如果窗口长度和要求的s1长度相同,说明不包含冗余字符,符合要求,输出true return True if d in needs:#窗口长度和要求的s1长度不同,要进行滑窗,如果即将剔除的字符d是目标字符之一 if windows[d] == needs[d]:#如果窗口中的d字符是找够了的,但剔除后,这个字符就少了一个,就不是数量找够的字符了,那么将已找够的字母数-1 voiad -= 1 windows[d] = windows[d] - 1#窗口中的d也-1 return False

浙公网安备 33010602011771号