zoukankan      html  css  js  c++  java
  • 图解leetcode —— 395. 至少有K个重复字符的最长子串

    前言:

    每道题附带动态示意图,提供java、python两种语言答案,力求提供leetcode最优解。

    描述:

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

    示例 1:

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

    输出:
    3

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


    示例 2:

    输入:
    s = "ababbc", k = 2

    输出:
    5

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

    思路:

    这道题可以用滑动窗口+分治的方法进行解答。

    java:

    class Solution {
    
        /**
         * 计算最长重复子串长度.
         *
         * @param s 字符串
         * @param k 重复次数
         * @return 长度
         */
        public int longestSubstring(String s, int k) {
            int len = s.length();
            if (len == 0 || k > len) {
                return 0;
            }
            if (k < 2) {
                return len;
            }
            return countHandler(s.toCharArray(), k, 0, len - 1);
        }
    
        /**
         * 计算最长重复子串长度逻辑处理
         *
         * @param chars 字符数组
         * @param k     重复次数
         * @param start 开始位置
         * @param end   结束位置
         * @return 长度
         */
        private int countHandler(char[] chars, int k, int start, int end) {
            if (k > end - start + 1) {
                return 0;
            }
            // 计数器,26代表个字母
            int[] times = new int[26];
            // 统计字符频率
            for (int i = start; i <= end; i++) {
                ++times[chars[i] - 'a'];
            }
            // 起点、终点夹逼,去掉首位不符合条件的字符串(滑动窗口)
            while (k <= end - start + 1 && times[chars[start] - 'a'] < k) {
                start++;
            }
            while (k <= end - start + 1 && times[chars[end] - 'a'] < k) {
                end--;
            }
            if (k > end - start + 1) {
                return 0;
            }
            // 字符串中间存在不符合条件的字符,即以该字符串为界,分割前子串和后字串,进行计算(分治)
            for (int i = start; i <= end; i++) {
                if (times[chars[i] - 'a'] < k) {
                    return (Math.max(countHandler(chars, k, start, i - 1), countHandler(chars, k, i + 1, end)));
                }
            }
            return end - start + 1;
        }
    }

    结果:

    python3:

    class Solution:
        def longestSubstring(self, s: str, k: int) -> int:
            length = len(s)
            if length == 0 or k > length:
                return 0
            if k < 2:
                return length
    
            def countHandler(s: str, k: int, start: int, end: int) -> int:
                if k > end - start + 1:
                    return 0
                # 初始化数组
                times = [0 for i in range(0, 27)]
                for i in range(start, end + 1):
                    times[ord(s[i]) - ord('a')] += 1
                # 起点、终点夹逼,去掉首位不符合条件的字符串(滑动窗口)
                while end - start + 1 >= k > times[ord(s[start]) - ord('a')]:
                    start += 1
                while end - start + 1 >= k > times[ord(s[end]) - ord('a')]:
                    end -= 1
                if k > end - start + 1:
                    return 0
                # 字符串中间存在不符合条件的字符,即以该字符串为界,分割前子串和后字串,进行计算(分治)
                for i in range(start, end):
                    if times[ord(s[i]) - ord('a')] < k:
                        return max(countHandler(s, k, start, i - 1), countHandler(s, k, i + 1, end))
                return end - start + 1
    
            return countHandler(s, k, 0, length - 1)

    结果:

  • 相关阅读:
    各种blog尝试后,发现wordpress适用起来最方便
    索引器(C# 编程指南)
    vue3 父子组件之间的传值
    vue3 + vite + ts 搭建项目
    vue3中使用全局变量
    用JSONKit库解析json文件
    程序内部让用户直接上appstore评价游戏的链接地址以及跳转方法
    常见错误:Apple MachO Linker Error
    常见错误:多线程界面元素显示错误
    常见错误:Undefined symbols for architecture i386
  • 原文地址:https://www.cnblogs.com/nedulee/p/12013803.html
Copyright © 2011-2022 走看看