给定两个字符串
s1
和s2
,写一个函数来判断s2
是否包含s1
的某个变位词。换句话说,第一个字符串的排列之一是第二个字符串的 子串
示例 1:
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").
示例 2:输入: s1= "ab" s2 = "eidboaoo"
输出: False
变位词:
我们可以简单理解为无论字符如何排序,只要确保字符中的所有字符出现的次数和原先字符中所有字符出现的次数一致即可。
我们可以发现变位词和原单词之间具有如下关系:
1. 所以字符出现的次数都是一样。
- 通过 Map 数据结构来做字符和出现次数的映射关系。
2. 字符串均保持连续性。
- 连续性 很容易想到可以使用 滑动窗口 的性质
1. 使用长度为26的数组记录s1中的字母出现次数,在对应位置+1
2. 使用长度与s1相等的滑动窗口在s2中判断子字符串是否为变位词,方法是在对应位置-1,判断数组是否全为0;
3. 窗口向前滑动,头部移除的字母重新+1,新加入的字母-1,再次判断。
class Solution {
public boolean checkInclusion(String s1, String s2) {
int len1 = s1.length();
int len2 = s2.length();
if(len1 > len2){
return false;
}
int[] arr1 = new int[26];
int[] arr2 = new int[26];
for(int i = 0; i<len1; i++){
arr1[s1.charAt(i) - 'a']++;
arr2[s2.charAt(i) - 'a']++;
}
int left = 0,right = s1.length();
while(right < s2.length()){
if(Arrays.equals(arr1,arr2)){
return true;
}
arr2[s2.charAt(right) - 'a']++;
arr2[s2.charAt(left) - 'a']--;
right++;
left++;
}
return Arrays.equals(arr1,arr2);
}
}