滑动窗口:给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。

一、题目描述

给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。

换句话说,第一个字符串的排列之一是第二个字符串的子串。

示例1:

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

示例2:

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

注意:

输入的字符串只包含小写字母
两个字符串的长度都在 [1, 10,000] 之间

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

二、题解 

    其实我们并不需要生成字符串的所有排列,只需要将第一个字符串的各个字符及其个数用map存起来,然后在第二个字符串中取与s1等长的字符串,也用map存起来,然后对比两个map中相同的字符,它的个数是否相同,如果相同的话,就能说明第一个字符串的排列之一是第二个字符串的子串。

    然后就是应用滑动窗口的思想,这里只要就是用到将窗口平移的手段,因为我们是要取与s1等长的字符串嘛,详细看下面代码

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        if(s1.length()>s2.length())
            return false;
        int map1[26]={0};
        int map2[26]={0};
        for(int i=0;i<s1.length();i++)
        {
            map1[s1[i]-'a']++;                //初始化第一个map
            map2[s2[i]-'a']++;                //初始化第二个map
        }
        for(int i=0;i<s2.length()-s1.length();i++)
        {
            if(match(map1,map2))              //判断两个map是否相同
            {
                return true;
            }
            map2[s2[i+s1.length()]-'a']++;    //窗口整体向右移动一步
            map2[s2[i]-'a']--;
        }
        if(match(map1, map2))
            return true;
        else
            return false;
    }
    bool match(int * map1, int * map2)
    {
        for(int i=0;i<26;i++)
        {
            if(map1[i]!=map2[i])
                return false;
        }
        return true;
    }

};

三、总结

    1.正如我在《滑动窗口:替换后的最长字符串》中提到,滑动窗口主要有三种手段,这里只要使用了平移的方法。

    2.这里也是用了map。

    3.把生成排列的问题转换成比较map的问题。

原创文章 26 获赞 33 访问量 1906

猜你喜欢

转载自blog.csdn.net/qq_40765537/article/details/105596471
今日推荐