【LeetCode 每日一题】3713. 最长的平衡子串 I ——(解法二)暴力枚举 + 优化

Problem: 3713. 最长的平衡子串 I

文章目录

  • [1. 整体思路](#1. 整体思路)
  • [2. 完整代码](#2. 完整代码)
  • [3. 时空复杂度](#3. 时空复杂度)
      • [时间复杂度: O ( N 2 ) O(N^2) O(N2)](#时间复杂度: O ( N 2 ) O(N^2) O(N2))
      • [空间复杂度: O ( 1 ) O(1) O(1) 或 O ( N ) O(N) O(N)](#空间复杂度: O ( 1 ) O(1) O(1) 或 O ( N ) O(N) O(N))

1. 整体思路

核心问题

寻找最长子串 s[i...j],使得该子串中所有出现过的字符的出现次数都相同。

算法逻辑:优化的暴力枚举

  1. 枚举所有子串

    • 依然使用双重循环遍历所有子串 [i, j]
  2. 实时维护最大频率和字符种类数

    • 在内层循环中,我们不需要每次都遍历 cnt 数组来检查平衡性。
    • 我们维护两个关键变量:
      • max:当前子串 [i, j] 中出现的最大频率 。每当某个字符频率增加时,更新 max
      • diff:当前子串 [i, j] 中出现的不同字符的个数 (Different Characters)。每当某个字符频率从 0 变为 1 时,diff++
  3. 快速判断平衡性

    • 如果一个子串是平衡的,意味着其中所有 diff 种字符的出现次数都必须相等,且必须等于最大频率 max
    • 因此,子串的总长度 len = j - i + 1 必须等于 max * diff
    • 判断公式max * diff == len
      • 如果相等,说明所有出现的字符频率都是 max,子串平衡。更新 ans
      • 如果不相等,说明有些字符频率小于 max,子串不平衡。

2. 完整代码

java 复制代码
class Solution {
    public int longestBalanced(String s) {
        // 转换为字符数组,提高访问效率
        char[] cs = s.toCharArray();
        int n = cs.length;
        int ans = 0;
        
        // 1. 枚举子串起始位置 i
        for (int i = 0; i < n; i++) {
            // cnt 数组用于统计当前子串 [i, j] 中每个字符的频率
            int[] cnt = new int[26];
            
            // max: 当前子串中的最大频率
            int max = 0;
            
            // diff: 当前子串中出现的不同字符种类数
            int diff = 0;
            
            // 2. 枚举子串结束位置 j
            for (int j = i; j < n; j++) {
                int b = cs[j] - 'a'; // 当前字符索引
                
                // 如果这是该字符第一次出现,说明遇到了一种新字符
                if (cnt[b] == 0) {
                    diff++;
                }
                
                // 更新当前字符的频率,并尝试更新最大频率 max
                max = Math.max(max, ++cnt[b]);
                
                // 3. 快速判断平衡性
                // 子串长度 len = j - i + 1
                // 理想总长度 = 最大频率 * 不同字符数
                // 如果两者相等,说明所有字符的频率都必须是 max,即平衡
                if (max * diff == j - i + 1) {
                    ans = Math.max(ans, j - i + 1);
                }
            }
        }
        
        return ans;
    }
}

3. 时空复杂度

假设字符串长度为 N N N。

时间复杂度: O ( N 2 ) O(N^2) O(N2)

  • 计算依据
    • 双重循环枚举子串,总次数为 N ( N + 1 ) 2 \frac{N(N+1)}{2} 2N(N+1)。
    • 内部所有操作(更新 cnt, max, diff, 判断)均为 O ( 1 ) O(1) O(1) 的常数操作。
  • 结论 : O ( N 2 ) O(N^2) O(N2)。
    • 相比上一版消除了 C = 26 C=26 C=26 的因子。

空间复杂度: O ( 1 ) O(1) O(1) 或 O ( N ) O(N) O(N)

  • 计算依据
    • cnt 数组固定大小 26。
    • toCharArray 需要 O ( N ) O(N) O(N) 空间。如果不计输入副本,额外空间为 O ( 1 ) O(1) O(1)。
  • 结论 : O ( N ) O(N) O(N)。
相关推荐
ZPC821018 小时前
moveit2_servo 怎么接收相机调节指令(视觉伺服)
人工智能·数码相机·算法·计算机视觉·机器人
灰灰勇闯IT18 小时前
CANN Graph Engine 执行链路:一张计算图如何跑上昇腾 NPU
人工智能·深度学习·算法
Gigavision18 小时前
SEED-VII 数据集介绍:面向七类情绪识别的 EEG 与眼动多模态数据集
人工智能·python·算法·脑机接口
KaMeidebaby18 小时前
卡梅德生物技术快报|Fab 抗体文库构建标准化实验流程与数据复盘
服务器·前端·数据库·人工智能·算法
想唱rap18 小时前
IO多路转接之epoll
linux·运维·服务器·数据库·网络协议·算法·http
zcg194218 小时前
图像分割——常用数据和算法
算法
子午18 小时前
基于YOLO的车牌识别检测~Python+YOLOV8算法+车牌定位+车牌检测+深度学习
python·算法·yolo
heimeiyingwang19 小时前
【架构实战】分布式ID生成:雪花算法与业务ID设计
分布式·算法·架构
代码中介商19 小时前
排序算法完全指南(一):冒泡排序深度详解
算法·排序算法
灰灰勇闯IT19 小时前
MindSpore 和 CANN 是什么关系——用一个厨房讲明白
人工智能·深度学习·算法·cann