LeetCode:字符串的排列【567】
題目描述
給定兩個字符串 s1 和 s2,寫一個函數來判斷 s2 是否包含 s1 的排列。
換句話說,第一個字符串的排列之一是第二個字符串的子串。
示例1:
輸入: s1 = "ab" s2 = "eidbaooo" 輸出: True 解釋: s2 包含 s1 的排列之一 ("ba").
示例2:
輸入: s1= "ab" s2 = "eidboaoo" 輸出: False
注意:
- 輸入的字符串只包含小寫字母
- 兩個字符串的長度都在 [1, 10,000] 之間
題目分析
1.這道題,我們用到的算法是滑動窗口,思路大體是這樣的:
首先字符串s1的排列的可能性應該是它的長度的階乘,因為字符串長度可能為10000,所以找出所有排列情況是不太可能。我們可以轉換思路,不要關注排列的形式,而是關注排列中元素的數量關系,比如aab,那么,轉換為數量關系就是{a:2,b:1},因為S1長度為3,所以我們的窗口長度也為3,如果我們在S2的找到了這樣一個窗口符合出現a的次數是兩個,b是一個,那么S2就是包含S1的排列的。
2.什么是滑動窗口啊?
窗口表示的數組內我們重點關注的一塊范圍,比如此處的范圍是e~i
滑動的意思及時,這個窗口會動,但是窗口的大小不變,比如此時右滑一位時,e就會離開,d就會加入。
3.再來理解一遍題?
我們說了,不要關注排列的形式,而是關注排列中元素的數量關系,比如aab,那么,轉換為數量關系就是{a:2,b:1},因為S1長度為3,所以我們的窗口長度也為3,如果我們在S2的找到了這樣一個窗口符合出現a的次數是兩個,b是一個,那么S2就是包含S1的排列的。換到這個題中,同理:
所以,輸出為True。
Java題解
class Solution { public boolean checkInclusion(String s1, String s2) { int l1 = s1.length(); int l2 = s2.length(); int[] c1 = new int[26]; int[] c2 = new int[26]; for(char c : s1.toCharArray()) c1[c-'a']++; for(int i=0;i<l2;i++) { if(i>=l1) --c2[s2.charAt(i-l1)-'a'];//先把坐標查過的 c2[s2.charAt(i)-'a']++; if(Arrays.equals(c1, c2)) return true; } return false; } }