字符串的排列--java
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
换句话说,s1 的排列之一是 s2 的 子串 。
示例 1:
输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").
示例 2:
输入:s1= "ab" s2 = "eidboaoo"
输出:false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-in-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
public class Solution {
public boolean checkInclusion(String s1, String s2) {
char[] ch1 = s1.toCharArray(); //把字符串变成数组形式
char[] ch2 = s2.toCharArray();
int len1 = s1.length(); //长度变量
int len2 = s2.length();
int[] str1 = new int[26]; //因为是小写,所以只需要有26和长度的数组即可,但是需要减'a'去偏移,记录元素出现的次数
int[] str2 = new int[26];
for (int i = 0; i < len1; i++) { //遍历ch1数组元素,并且使用str1数组来记录出现的频率
str1[ch1[i] - 'a']++; //注意,'z=123',所以我们要减去'a'这个偏移量
}
int count = 0; //计数器
for (int i = 0; i < 26; i++) { //遍历str1数组,使用计数器来代表str1数组元素右多少个
if (str1[i] > 0){
count++;
}
}
int left = 0; //滑动窗口指针
int right = 0;
// 当滑动窗口中的某个字符个数与 s1 中对应相等的时候才计数
int winCount = 0;
while (right < len2){ //滑动窗口始终在len2长度以内
if (str1[ch2[right] - 'a'] > 0 ) { //找到ch2中右指针指向的元素在str1数组中的频率
str2[ch2[right] - 'a']++; //在str2数组中为ch2数组右指针指向的元素频率+1
if (str2[ch2[right] - 'a'] == str1[ch2[right] - 'a']){ //当str2和str1中的相同元素频率相同,才代表字符符合
winCount++; //当一个元素在str1和str2出现的频率一致
}
}
right++; //更新右指针,一直找到当滑动创口中包含元素的频率域str1中ch2数组右指针指向元素的频率一致时
while (count == winCount){ //当计数器和相同元素频率一致时
if (right - left == len1){ //找到了
return true;
}
if (str1[ch2[left] - 'a'] > 0 ) { //str1频率数组中ch2左指针元素频率大于0
str2[ch2[left] - 'a']--; //str2频率数组中ch2左指针元素频率-1
if (str2[ch2[left] - 'a'] < str1[ch2[left] - 'a']){
winCount--; //当一个元素在str2存在的频率小于str1存在的频率,说明此时滑动窗口不包含
}
}
left++; //更新左指针
}
}
return false;
}
}