至少有k個字串 遞迴的實踐

2021-10-20 16:26:44 字數 1403 閱讀 4466

給你乙個字串s和乙個整數k,請你找出s中的最長子串, 要求該子串中的每一字元出現次數都不少於k。返回這一子串的長度。

本題要求的乙個最長的子字串的長度,該子字串中每個字元出現的次數都最少為 k。

求最長子字串/區間的這類題一般可以用滑動視窗來做,但是本題滑動視窗的**不好寫,我改用遞迴。也借本題來幫助大家理解遞迴。

重點:我們在呼叫遞迴函式的時候,把遞迴函式當做普通函式(黑箱)來呼叫,即明白該函式的輸入輸出是什麼,而不用管此函式內部在做什麼。

遞迴最基本的是記住遞迴函式的含義(務必牢記函式定義):本題的 longestsubstring(s, k) 函式表示的就是題意,即求乙個最長的子字串的長度,該子字串中每個字元出現的次數都最少為 k。函式入參 s 是表示源字串;k 是限制條件,即子字串中每個字元最少出現的次數;函式返回結果是滿足題意的最長子字串長度。

遞迴的終止條件(能直接寫出的最簡單 case):如果字串 s 的長度少於 k,那麼一定不存在滿足題意的子字串,返回 0;

呼叫遞迴(重點):如果乙個字元 c 在 s **現的次數少於 k 次,那麼 s 中所有的包含 c 的子字串都不能滿足題意。所以,應該在 s 的所有不包含 c 的子字串中繼續尋找結果:把 s 按照 c 分割(分割後每個子串都不包含 c),得到很多子字串 t;下一步要求 t 作為源字串的時候,它的最長的滿足題意的子字串長度(到現在為止,我們把大問題分割為了小問題(s → t))。此時我們發現,恰好已經定義了函式 longestsubstring(s, k) 就是來解決這個問題的!所以直接把 longestsubstring(s, k) 函式拿來用,於是形成了遞迴。

未進入遞迴時的返回結果:如果 s 中的每個字元出現的次數都大於 k 次,那麼 s 就是我們要求的字串,直接返回該字串的長度。

class solution3 ; //記錄每個字元出現的次數

for (auto c : s) ++m[c - 'a'];

int i = 0;

while (i < length && m[s[i] - 'a'] >= k) ++i;

if (i == length) return length;

int left = longestsubstring(s.substr(0, i), k);

while (i < length && m[s[i] - 'a'] < k) ++i;

int right = longestsubstring(s.substr(i), k);

return max(left, right);

}

參考:

至少有 K 個重複字元的最長子串

原題指路 至少有 k 個重複字元的最長子串 給你乙個字串s和乙個整數k,請你找出s中的最長子串,要求該子串中的每一字元出現次數都不少於k。返回這一子串的長度。這道題有別於一般的 滑動視窗 的題目,因為這道題視窗的維護條件需要人為新增一項,即視窗中的字元種類數。雖然這看起來很複雜,但是由於這題的資料範...

395 至少有 K 個重複字元的最長子串

給你乙個字串 s 和乙個整數 k 請你找出 s 中的最長子串,要求該子串中的每一字元出現次數都不少於 k 返回這一子串的長度。示例 1 輸入 s aaabb k 3 輸出 3 解釋 最長子串為 aaa 其中 a 重複了 3 次。示例 2 輸入 s ababbc k 2 輸出 5 解釋 最長子串為 a...

395 至少有K個重複字元的最長子串

殘疾人 訓練 題目 給你乙個字串s和乙個整數k,請你找出s中的最長子串,要求該子串中的每一字元出現次數都不少於k。返回這一子串的長度。最開始的時候一頭霧水 因為我是殘疾人 求子串的問題,在我看來,最難的地方就是時間複雜度 因為隨著字串長度的增加,全部字串的數量是呈指數級別上公升的,因此所有基於列舉所...