📌  相关文章
📜  所有字符至少出现 K 次的最大子串 | 2套(1)

📅  最后修改于: 2023-12-03 14:54:26.428000             🧑  作者: Mango

所有字符至少出现 K 次的最大子串

给定一个字符串s和一个整数k,找到一个最长的子串,使得该子串中所有字符至少出现k次。

方法一:滑动窗口

先用一个hash_map(或是字典)记录每个字符在当前窗口中的出现次数,然后从左到右遍历整个字符串,每次移动右指针扩大窗口,并更新窗口内每个字符的出现次数。如果窗口中某个字符的出现次数小于k,则将左指针也向右移动,并更新窗口内每个字符的出现次数,直到左指针到达当前滑动窗口的最右端或是窗口中的每个字符都出现了至少k次。

代码如下:

class Solution:
    def longestSubstring(self, s: str, k: int) -> int:
        max_len = 0
        # 遍历不同的出现次数
        for num_unique_target in range(1, len(set(s))+1):
            hash_map = [0]*26
            left = right = 0  # 左右指针初始化
            num_unique = num_no_less_than_k = 0
            # 移动右指针
            while right < len(s):
                if hash_map[ord(s[right])-ord('a')] == 0:
                    num_unique += 1
                hash_map[ord(s[right])-ord('a')] += 1
                if hash_map[ord(s[right])-ord('a')] == k:
                    num_no_less_than_k += 1
                right += 1
                # 移动左指针
                while num_unique > num_unique_target:
                    if hash_map[ord(s[left])-ord('a')] == k:
                        num_no_less_than_k -= 1
                    hash_map[ord(s[left])-ord('a')] -= 1
                    if hash_map[ord(s[left])-ord('a')] == 0:
                        num_unique -= 1
                    left += 1
                # 更新最大长度
                if num_unique == num_unique_target and num_unique == num_no_less_than_k:
                    max_len = max(max_len, right - left)
        return max_len
方法二:递归分治法

首先统计出每个字符在字符串中出现的次数,如果某个字符的出现次数小于k,则该字符肯定不会出现在所求的最长子串中。因此我们可以将该字符串以这个字符为分界线,将其分成若干段,分别递归求解。

代码如下:

class Solution:
    def longestSubstring(self, s: str, k: int) -> int:
        # 统计每个字符出现的次数
        counter = collections.Counter(s)
        # 找出所有不满足出现次数>=k的字符
        invalid_chars = [c for c, count in counter.items() if count < k]
        # 如果不存在不满足条件的字符,直接返回整个字符串长度
        if not invalid_chars:
            return len(s)
        # 以不满足条件的字符为分界线,将字符串分成若干段
        # 对每段进行递归调用,返回所有子串中的最长长度
        return max(self.longestSubstring(sub_str, k) for sub_str in re.split('|'.join(invalid_chars), s))