写这个学习笔记的原因是因为刷到LeetCode上这一题时发现有一个很巧妙的解法。
首先看一下题目:
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的 子串 。
示例 1:
输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").
示例 2:
输入: s1= "ab" s2 = "eidboaoo"
输出: False
解法大致思路:
如果s2包含s1的排列,就说明s2中有一段与s1一样长的子字符串中包含的每个字符的个数与s1包含的一样。
设n为s1的长度
- 维持一个固定长度为n的滑动窗口
- 在s2上滑动窗口,同时统计窗口内的每个字符的个数
- 每次往右滑动时,将原本窗口内的首字母移除一个,将右移后加进来的字母添加一个
- 每次滑动后,统计窗口内每个字符的个数是否与s1相同
这里有一个很巧妙的方法。就是在统计每个字符的个数时,可以用 char - ‘a'的方式把此char转换成int。例如‘a'-’a' = 0, ‘b'-’a' = 1 。。。用此方法就可以用一个数组来统计每个字符的个数,比如,“ABC”就会变成【1,1,1】, “ABB”就会变成【1,2】。
拿题目的例子来说:
s1 = "ab" s2 = "eidbaooo"
s1Arr = 【1,1】
然后在s2上维持一个长度为2的移动窗口, 每次移动时更新窗口所对应的数组,然后比较数组是否相等。如相等则代表此时窗口内的字字符串是s1的排列
以下是代码,参考 https://leetcode-cn.com/problems/permutation-in-string/solution/zi-fu-chuan-de-pai-lie-by-leetcode-solut-7k7u/
public static boolean checkInclusion2(String s1, String s2) {
char[] s1Chars = s1.toCharArray();
char[] s2Chars = s2.toCharArray();
int[] s1Arr = new int[26];
int[] temp = new int[26];
for (int i = 0; i < s1.length(); i++) {
s1Arr[s1Chars[i] - 'a']++;
temp[s2Chars[i] - 'a']++;
}
if (Arrays.equals(temp, s1Arr)) {
return true;
}
for (int i = s1.length(); i < s2.length(); i++) {
temp[s2Chars[i] - 'a']++;
temp[s2Chars[i - s1.length()] - 'a']--;
if (Arrays.equals(temp, s1Arr)) {
return true;
}
}
return false;
}
本人小白,写的不好请指教!!