1. 程式人生 > 其它 >劍指 Offer II 014. 字串中的變位詞

劍指 Offer II 014. 字串中的變位詞

給定兩個字串 s1 和 s2,寫一個函式來判斷 s2 是否包含 s1 的某個變位詞。

換句話說,第一個字串的排列之一是第二個字串的 子串 。

 

示例 1:

輸入: s1 = "ab" s2 = "eidbaooo"
輸出: True
解釋: s2 包含 s1 的排列之一 ("ba").

示例 2:

輸入: s1= "ab" s2 = "eidboaoo"
輸出: False

 

提示:

    1 <= s1.length, s2.length <= 104
    s1 和 s2 僅包含小寫字母


解析:

  vis記錄s1中每個字母出現的次數

  遍歷s2,如果遇到一個s1中的字母temp,vis1[temp]++,即vis1用來記錄當前所遇到的s1中相應字母的個數

  如果vis1[temp] >= vis[temp],說明當前位置i的字母出現多了,那麼就刪去第一次出現的temp

  試想 如果刪去了第一次出現的temp,那麼這個連續子串就中斷了,所以從這個連續子串開始的位置第一次出現temp的位置的字母都要刪去

  更新子串開始位置為第一次出現temp位置的下一個位置

  二維queue記錄每個字母的出現位置

  刪去的時候,相應的queue  pop就可以,即更新每個字母第一次出現的位置

  

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        
int vis[30], vis1[30]; memset(vis, 0, sizeof(vis)); queue<int> q[30]; memset(vis1, 0, sizeof(vis1)); int len1 = s1.length(); for(int i = 0; i < len1; i++) { vis[s1[i] - 'a']++; } int ans = len1, cnt = 0, len2 = s2.length(), start;
for(int i = 0; i < len2; i++) { if(cnt == ans) { return true; } int temp = s2[i] - 'a'; if(vis[temp]) { if(vis1[temp] >= vis[temp]) { int ll = q[temp].front(); for(int j = start; j <= ll; j++) vis1[s2[j] - 'a']--, cnt--, q[s2[j] - 'a'].pop(); start = ll + 1; } if(cnt == 0) start = i; vis1[temp]++, cnt++; q[temp].push(i); } else { for(int j = 0; j < 30; j++) while(!q[j].empty()) q[j].pop(); memset(vis1, 0, sizeof(vis1)); cnt = 0; } } return cnt == ans ? true : false; } };