寫這個學習筆記的原因是因為刷到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;
}
本人小白,寫的不好請指教!!