【leetcode】395. 至少有K個重複字符的最長子串

題目

找到給定字符串(由小寫字符組成)中的最長子串 T , 要求 T 中的每一字符出現次數都不少於 k 。輸出 T 的長度。

示例 1:

輸入:
s = “aaabb”, k = 3

輸出:
3

最長子串爲 “aaa” ,其中 ‘a’ 重複了 3 次。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/longest-substring-with-at-least-k-repeating-characters
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

思路

這個題目一開始我是用的滑動窗口的思路。
首先統計一下字符串中每個字符的個數,當滑動窗口的滑到一個字符的個數小於k的時候就縮小窗口,統計一下窗口內部滿足條件的子串的長度。然後就有一些小小的問題,比如說str = “abbbaca”, k = 3。
當滑動窗口第一次停下來,進行內部元素統計的時候是 abbba , 這個時候,怎麼縮小滑動窗口就有些困難。因爲需要將l, r 同時進行一個調整。
我感覺滑動窗口的解決思路是首先獲得一個[l, r]最大最小的可行解空間,然後增大l, 求一個最優解。但是,滑動到第二個a的時候,我無法得知abbb是一個最小的可行解,只有滑動到c的時候,我才知道abbbac是一個可行解,但不是最小的可行解,就造成了需要同時調整l, r。
所以就可以採用一個分治的思想,將原問題劃分問一些子問題和另一些子問題,然後分別進行處理,因爲無法很好的分成一個子問題和另一些子問題。
所以採用了遞歸分治的做法

代碼

class Solution {
public:
    int longestSubstring(string s, int k) {
        if (k <= 1) return s.size();
        if (s.empty() || s.size() < k) return 0;
        
        vector<int> hash(128, 0);
        for (char c : s) ++hash[c];
        
        int i = 0;
        while (i < s.size() && hash[s[i]] >= k) ++i;
        if (i == s.size()) return s.size();

        int l = longestSubstring(s.substr(0, i), k);
        while (i < s.size() && hash[s[i]] < k) ++i;
        int r = longestSubstring(s.substr(i), k);
        
        return max(l, r);
    }
};

總結

滑動窗口應該是分治法的一個特例,
滑動窗口是將問題分成了一個子問題和另一些子問題
窗口內部就是一個子問題,然後在這個子問題內部求一個最優解

而這個題目,不太容易將問題劃分爲一個子問題和另一些子問題,
但是劃分爲一些子問題和另一些子問題比較容易,
所以就用一個遞歸的方法來解決。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章