字符串的排列

给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。

换句话说,s1 的排列之一是 s2 的 子串 。

示例 1:

输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").
示例 2:

输入:s1= "ab" s2 = "eidboaoo"
输出:false
 

提示:

1 <= s1.length, s2.length <= 104
s1 和 s2 仅包含小写字母

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-in-string
 

思路:涉及到子串问题,我们考虑利用滑动窗口来解决。若s2包含s1的任意一个排列,则滑动窗口(在s2上滑动)的长度必定与s1相当,且窗口与s1中各个字符出现的次数相等。

具体过程是:先固定左指针left,我们遍历右指针right,不断扩大滑动窗口,对s1中存在的元素进行计数,当某个字符在s2中出现的次数==在s1中出现的次数,我们让winCount++。显然,当winCount的值与字符种类数count相等的时候,我们就应该开始缩小滑动窗口,当滑动窗口长度与s1长度相当的时候,返回true,否则返回false

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        //s1字符数组和s2字符数组
        char[] s1Char = s1.toCharArray();
        char[] s2Char = s2.toCharArray();
        //记录s1和s2中各个字符出现的次数
        int[] s1CharCount = new int[26];
        int[] s2CharCount = new int[26];
        //s1的字符种类
        int count = 0;
        //记录s2中,字符出现次数与s1中该字符出现次数相等(或者大于)的字符的个数
        int winCount = 0;
        //滑动窗口的左右指针
        int left = 0;
        int right = 0;
        //遍历s1Char,初始化s1CharCount,记录各个字符出现的次数
        for(int i=0;i<s1Char.length;i++){
            s1CharCount[s1Char[i]-'a']++;
        }
        //求得count
        for(int i=0;i<s1CharCount.length;i++){
            if(s1CharCount[i]>0){
                count++;
            }
        }
        //遍历s2数组(或者说是遍历s2字符串)
        while(right<s2Char.length){
            //获取right指向字符在数组中的下标
            int dex = s2Char[right] - 'a';
            //如果s2的该字符在s1中出现过,就在s2的计数数组中也进行技术
            if(s1CharCount[dex]>0){
                s2CharCount[dex]++;
                if(s1CharCount[dex]==s2CharCount[dex]){
                winCount++;
                }
            }
            right++;
            //满足此条件时,滑动窗口内的字符种类和数量均满足条件
            while(winCount==count){
                //长度相当,必定满足条件
                if(right-left==s1.length()){
                    return true;
                }
                //长度不相当,缩小窗口,移动左指针
                //获取left指向字符在数组中的下标
                dex = s2Char[left] - 'a';
                //如果left所指的s2的字符在s1中存在
                if(s1CharCount[dex]>0){
                    //在s2中剔除一次该字符
                    s2CharCount[dex]--;
                    if(s2CharCount[dex]<s1CharCount[dex]){
                        winCount--;
                    }
                }
                left++;
            }
        }
        return false;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值