*Leetcode 395. Longest Substring with At Least K Repeating Characters

一个不太难的题,不算dp,最早写的一版200多ms才A掉

const int SZ = 26;
class Solution {
public:
    int longestSubstring(string s, int t) {
        if (!s.size() || t > s.size()) return 0;
        int prefix[26][s.size()];
        int suffix[26][s.size()];
        int dp[s.size()][s.size()];
        for (int i = 0; i < s.size(); i++) {
            for(int j = 0; j < 26; j++) {
                prefix[j][i] = (s[i] - 'a')==j;
                if (i != 0) 
                    prefix[j][i] += prefix[j][i-1];
            }
        }
        for (int i = s.size() - 1; i >= 0; i--) {
            for (int j = 0; j < 26; j++) {
                suffix[j][i] =  ( (s[i] - 'a')==j );
                if (i != s.size()-1) 
                    suffix[j][i] += suffix[j][i+1];
            }
        }
        int ans = 0, en = s.size()-1;
        for (int i = 0; i < s.size(); i++) {
            for (int j = i; j < s.size(); j++) {
                bool ok = true;
                int k = s[i] - 'a';
                int cnt = prefix[k][j] + suffix[k][i] - prefix[k][en];
                if (cnt && cnt < t) continue;
                for (int k = 0; k < 26; k++) {
                    int cnt = prefix[k][j] + suffix[k][i] - prefix[k][en];
                    if (cnt && cnt < t) {
                        ok = false;
                    } 
                    // if (cnt >= t) {
                    //     cout << "cnt:" << cnt << " c:" << (char)('a' + k) << endl;
                    // }
                }
                if (ok) {
                    ans = max(ans, j - i + 1);
                    // cout << "i:" << i << " j:" << j << endl;
                }
            }
        }
        return ans;
    }
};

然后想了下,可以省略一些操作,使用一个数组bigger,维护>=k的字母的长度和。160多ms过掉。

const int SZ = 26;
class Solution {
public:
    int longestSubstring(string s, int t) {
        if (!s.size() || t > s.size()) return 0;
        int prefix[26][s.size()];
        int bigger[s.size()];
        
        for (int i = 0; i < s.size(); i++) {
            for(int j = 0; j < 26; j++) {
                prefix[j][i] = (s[i] - 'a')==j;
                if (i != 0) 
                    prefix[j][i] += prefix[j][i-1];
            }
        }

        int ans = 0, en = s.size()-1;
        for (int i = 0; i < s.size(); i++) {
            // memset(bigger, sizeof(bigger), 0);
            for (int j = i; j < s.size(); j++) {
                bigger[j] = j == i ? 0 : bigger[j-1];
                // bool ok = true;
                int k = s[j] - 'a';
                int cnt = prefix[k][j]; 
                if (i) cnt -= prefix[k][i - 1];
                
                if (cnt < t) {
                    continue;
                } else {
                    if (cnt == t) {
                        bigger[j] += t;
                    } else {
                        bigger[j] += 1;
                    }
                }

                if (bigger[j] < j - i + 1) continue;
                ans = max(ans, j - i + 1);

            }
        }
        return ans;
    }
};

然后看了下答案,大概170ms过的,用了mask位运算来记录有多少个字母>=k, 思路也很简单,就是每个位表示是不是>=k,是为1,否则为0,这样的话符合更新ans条件的时候mask == 0 有意思

class Solution {
public:
int longestSubstring(string s, int k) {
   int max_len = 0;
   for (int first = 0; first+k <= s.size();) {
       int count[26] = {0};
       int mask = 0;
       int max_last = first;
       for (int last = first; last < s.size(); ++last) {
           int i = s[last] - 'a';
           count[i]++;
           if (count[i]



你可能感兴趣的:(*Leetcode 395. Longest Substring with At Least K Repeating Characters)