Jerry's Blog

Recording what I learned everyday

View on GitHub


26 November 2020

LeetCode(395) -- Longest Substring with At Least K Repeating Characters

by Jerry Zhang

Problem

找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。

输入:
s = "aaabb", k = 3

输出:
3

最长子串为 "aaa" ,其中 'a' 重复了 3 次。

Solution

class Solution {
    public int longestSubstring(String s, int k) {
        char[] str = s.toCharArray();
        int[] countMap = new int[26];
        int maxUnique = getMaxUniqueLetters(s);
        int result = 0;
        for (int currUnique = 1; currUnique <= maxUnique; currUnique++) {
            Arrays.fill(countMap, 0);
            int windowStart = 0, windowEnd = 0, idx = 0, unique = 0, countAtLeastK = 0;
            while (windowEnd < str.length) {
                if (unique <= currUnique) {
                    idx = str[windowEnd] - 'a';
                    if (countMap[idx] == 0) unique++;
                    countMap[idx]++;
                    if (countMap[idx] == k) countAtLeastK++;
                    windowEnd++;
                } else {
                    idx = str[windowStart] - 'a';
                    if (countMap[idx] == k) countAtLeastK--;
                    countMap[idx]--;
                    if (countMap[idx] == 0) unique--;
                    windowStart++;
                }
                if (unique == currUnique && unique == countAtLeastK)
                    result = Math.max(windowEnd - windowStart, result);
            }
        }
        return result;
    }
    
    int getMaxUniqueLetters(String s) {
        boolean map[] = new boolean[26];
        int maxUnique = 0;
        for (int i = 0; i < s.length(); i++) {
            if (!map[s.charAt(i) - 'a']) {
                maxUnique++;
                map[s.charAt(i) - 'a'] = true;
            }
        }
        return maxUnique;
    }
}

sliding window, 44%

The Best Solution

class Solution {
    public int longestSubstring(String s, int k) {
        return dfs(s, k,  0, s.length());
    }
    private int dfs(String s, int k, int begin, int end){
        int[] charNums = new int[26];
        for (int i = begin; i < end; i++){
            int idx = s.charAt(i) - 'a';
            charNums[idx]++;
        }
        int res = 0;
        int new_begin = begin;
        for (int i = begin; i < end; i++){
            int idx = s.charAt(i) - 'a';
            if (charNums[idx] > 0 && charNums[idx] < k) {
                if (i - new_begin >= k) res = Math.max(res, dfs(s, k, new_begin, i));
                new_begin = i+1;
            }
        }
        if (new_begin == begin) return end - begin;
        return Math.max(res, dfs(s, k, new_begin, end));
    }
}
tags: LeetCode