給定兩個字符串 s1 和 s2,寫一個函數來判斷 s2 是否包含 s1 的排列。
換句話說,第一個字符串的排列之一是第二個字符串的子串。
示例1:
輸入: s1 = "ab" s2 = "eidbaooo"
輸出: True
解釋: s2 包含 s1 的排列之一 ("ba").
示例2:
輸入: s1= "ab" s2 = "eidboaoo"
輸出: False
注意:
輸入的字符串只包含小寫字母
兩個字符串的長度都在 [1, 10,000] 之間
思路分析: 首先想到的是將第一個字符串全排列,然後用第二個逐個判斷,但這樣只能通過一部分就會超時。
正確的做法是使用滑動窗口的想法,使用兩個哈希表的方式做統計(實際使用的是vector<int> a(128)),我們先來分別統計s1和s2中前n1個字符串中各個字符出現的次數,其中n1爲字符串s1的長度,這樣如果二者字符出現次數的情況完全相同,說明s1和s2中前n1的字符互爲全排列關係,那麼符合題意了,直接返回true。如果不是的話,那麼我們遍歷s2之後的字符,對於遍歷到的字符,對應的次數加1,由於窗口的大小限定爲了n1,所以每在窗口右側加一個新字符的同時就要在窗口左側去掉一個字符,每次都比較一下兩個哈希表的情況,如果相等,說明存在
C ++代碼如下:
class Solution {
public:
bool checkInclusion(string s1, string s2) {
int n1=s1.size();
int n2=s2.size();
if(n1 > n2) return false;
vector<int> map1(128),map2(128);
for(int i=0; i<n1; i++)
{
map1[s1[i]]++;
map2[s2[i]]++;
}
if(map1 == map2) return true;
for(int i=n1;i<s2.size();i++)
{
map2[s2[i]]++;
map2[s2[i-n1]]--;
if(map1 == map2) return true;
}
return false;
}
};