各位题友大家好,今天是每日算法题公众号坚持日更的第 17 天。今天力扣上的每日一题是「567. 字符串的排列」。
题目大意
示例
数据范围
解题思路
滑动窗口 + 字典
题目要求 s1
的排列之一是 s2
的一个子串。而子串必须是连续的,所以要求的 s2
子串的长度跟 s1
长度必须相等。
那么我们有必要把 s1
的每个排列都求出来吗?当然不用。如果字符串 a
是 b
的一个排列,那么当且仅当它们两者中的每个字符的个数都必须完全相等。
所以,根据上面两点分析,我们已经能确定这个题目可以使用 滑动窗口 + 字典 来解决。
我们使用一个长度和 s1
长度相等的固定窗口大小的滑动窗口,在 s2
上面从左向右滑动,判断 s2
在滑动窗口内的每个字符出现的个数是否跟 s1
每个字符出现次数完全相等。
我们定义 counter1
是对 s1
内字符出现的个数的统计,定义 counter2
是对 s2
内字符出现的个数的统计。在窗口每次右移的时候,需要把右边新加入窗口的字符个数在 counter2
中加 1,把左边移出窗口的字符的个数减 1。如果 counter1 == counter2
,那么说明窗口内的子串是 s1
的一个排列,返回 True;如果窗口已经把 s2
遍历完了仍然没有找到满足条件的排列,返回 False。
躲坑指南:
- 本题中的
counter
可以用字典,也可以用数组来实现。用字典的时候,需要注意:如果移除left
元素后,若counter2[s2[left]] == 0
那么需要从字典中删除left
这个key。因为{"a":0, "b":1}
和{"b":1}
是不等的。 - 窗口的定义一定要搞清楚是否包含两边的端点,比如我定义的窗口是
[left, right]
两个端点都包含,那么就需要把两个端点的元素也放入counter2
中。 counter2
初始化的时候只放了[0, right - 1]
个元素,因为在while
循环中的第一行就是把right
元素放到counter2
中。
代码
使用 Python2 写的代码如下。注释超详细,其他语言可以对应修改。
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
刷题心得
今天这个题不难,是常规的固定窗口大小的滑动窗口问题。但是细节比较多,比如 counter2 初始化放多少个元素;当移除 left
指向元素的时候,如果此时该元素个数为 0,需要从字典中删除 key 等。
参考资料:
1. 力扣官方题解:字符串的排列
2. 负雪明烛博客:567. Permutation in String
3. 【LeetCode】代码模板,刷题必会
欢迎加入刷题群
目前已经近 2000 人加入了每日一题打卡群。加入方式是通过每日一题打卡网站。每天都会同步力扣每日一题,这是个互相帮助、互相监督的算法题打卡网站,其地址是 https://www.ojeveryday.com/
想加入千人刷题群的朋友,可以复制上面的链接到浏览器,然后在左侧点击「加入组织」,提交力扣个人主页,即可进入刷题群。期待你早日加入。
关于作者
我是本文的作者是负雪明烛,毕业于北京邮电大学,目前就职于阿里巴巴。坚持刷算法题 5 年,共计刷了 800 多道算法题。做过的每个算法题都在 CSDN 上写题解博客,获得好评无数,CSDN 的累计阅读量已经 160万 次!博客地址是:https://blog.csdn.net/fuxuemingzhu
「每日算法题」公众号是我维护的一个算法题解公众号,主要讲解算法题的解法,也会分享找工作的经验。欢迎关注。
题目来源:839. 相似字符串组https://leetcode-cn.com/problems/similar-string-groups/