字符串的排列
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例1:
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").
思路+代码+注释:
public boolean checkInclusion(String s1, String s2) {
/*
思路:采用滑动窗口的思想,滑动窗口的大小为s1的长度,滑动窗口最左边初始为s2的起始位置,统计滑动窗口中每个字符出现的个数和s1中每个字符出现个数进行比较,
如果相同那么s1必然有一种序列和滑动窗口中的字符串相同返回true,否则滑动窗口右移一位,将最左边字符的次数减1,最右边字符的次数+1
采用两个HashMap,存储s1中的字符以及字符出现次数和滑动窗口中的字符以及出现次数
*/
HashMap<Character,Integer> s1Map=new HashMap<>();
HashMap<Character,Integer> windowMap=new HashMap<>();
char[] charsOne=s1.toCharArray();
char[] charsTwo=s2.toCharArray();
for (char c:charsOne
) {
if (s1Map.containsKey(c))
{
s1Map.put(c,s1Map.get(c)+1);
}else {
s1Map.put(c,1);
}
}
Set<Character> s1KeySet=s1Map.keySet();
for (int i = 0; i < charsTwo.length; i++) {
char rightChar=charsTwo[i];
if (windowMap.containsKey(rightChar))
{
windowMap.put(rightChar,windowMap.get(rightChar)+1);
}else {
windowMap.put(rightChar,1);
}
if (i >= charsOne.length-1)
{
boolean flag=true;
//比较字符以及出现次数
for (Character c:s1KeySet
) {
if (windowMap.containsKey(c))
{
int windowCharCount=windowMap.get(c);
int sOneCharCount=s1Map.get(c);
if (windowCharCount!=sOneCharCount)
{
flag=false;
//最左边字符
char leftChar=charsTwo[i-(charsOne.length-1)];
//移动滑动窗口,将左边字符次数减1,减1后为0就删除该字符
int ciShu=windowMap.get(leftChar);
if (ciShu > 1)
{
windowMap.put(leftChar,ciShu-1);
}else {
windowMap.remove(leftChar);
}
break;
}
}else {
flag=false;
//最左边字符
char leftChar=charsTwo[i-(charsOne.length-1)];
//移动滑动窗口,将左边字符次数减1,减1后为0就删除该字符
int ciShu=windowMap.get(leftChar);
if (ciShu > 1)
{
windowMap.put(leftChar,ciShu-1);
}else {
windowMap.remove(leftChar);
}
break;
}
}
if (flag)
{
return true;
}
}
}
return false;
}