【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)。
相关推荐
罗西的思考1 天前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
_清歌3 天前
DSpark 深度解读:DeepSeek-V4 如何用「半自回归」把推理速度提升 85%
算法
统计实现局3 天前
SVD 的三步走:双对角化、Givens 收敛、排序
算法
躬行见万象3 天前
《VLA 系列》UniLab 强化训练 | G1 机器人 |复现
算法
统计实现局3 天前
对称不定分解(Bunch-Kaufman):为什么 Cholesky 不够用
算法