567. 字串的排列
阿新 • • 發佈:2021-02-11
給定兩個字串 s1
和 s2
,寫一個函式來判斷 s2
是否包含 s1
的排列。
換句話說,第一個字串的排列之一是第二個字串的子串。
示例1:
輸入: s1 = "ab" s2 = "eidbaooo"
輸出: True
解釋: s2 包含 s1 的排列之一 ("ba").
示例2:
輸入: s1= "ab" s2 = "eidboaoo"
輸出: False
注意:
- 輸入的字串只包含小寫字母
- 兩個字串的長度都在
[1, 10,000]
之間
解答
滑動視窗遍歷,通過記錄字串每個字母出現次數來判斷是否是排列。
class Solution {
public:
bool checkInclusion(string s1, string s2) {
if(s1.size() > s2.size())
return false;
vector<int> target(26, 0);
for(auto& c : s1){
target[c - 'a']++;
}
int left = 0;
for(int right = 0; right < s2.size(); right++){
if(right - left + 1 < s1.size())
continue;
string subs = s2.substr(left, right - left + 1);
if(isPermutation(subs, target)){
return true;
}
else{
left++;
}
}
return false;
}
bool isPermutation(string s, vector<int>& target){
vector<int> temp(26, 0);
for(auto& c : s){
temp[c - 'a']++;
}
for(int i = 0; i < 26; i++){
if(temp[i] != target[i])
return false;
}
return true;
}
};
實際上滑動視窗的大小是固定的,並且可以直接判斷兩個vector
是否相等:
class Solution {
public:
bool checkInclusion(string s1, string s2) {
if(s1.size() > s2.size())
return false;
// 還可以進一步優化,只使用一個vector來記錄下列兩個的差值。
vector<int> cnt1(26, 0);
vector<int> cnt2(26, 0);
for(int i = 0; i < s1.size(); i++){
cnt1[s1[i] - 'a']++;
cnt2[s2[i] - 'a']++;
}
if(cnt1 == cnt2)
return true;
for(int i = s1.size(); i < s2.size(); i++){
cnt2[s2[i] - 'a']++;
cnt2[s2[i - s1.size()] - 'a']--;
if(cnt1 == cnt2)
return true;
}
return false;
}
};