【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)。
相关推荐
带多刺的玫瑰12 小时前
Leecode#26刷题之删除有序数组中的重复项
数据结构·算法·leetcode
en.en..13 小时前
C语言核心解析:#define与typedef本质区别
开发语言·c++·算法
YonyouHRSaaS14 小时前
AI视频面试系统定义、功能作用、品牌推荐、选择攻略
人工智能·面试·职场和发展·ai面试·视频面试·ai视频面试
zihan51815 小时前
理论:构建“基于客观事实、可量化、闭环自给自足”的个人操作系统
笔记·职场和发展·学习方法
wabs66615 小时前
关于二叉树【429.N叉树的层序遍历的思考】
数据结构·c++·算法·leetcode·二叉树
hetao173383715 小时前
2026-09-08 hetao1733837 的刷题记录
c++·算法
C++ 老炮儿的技术栈16 小时前
MFC CPtrArray的用法
开发语言·数据结构·c++·算法·mfc·c
小鱼爱吃草灬灬16 小时前
实时面试辅助排查清单:音频来源、问题输入与上下文
面试·职场和发展·音视频
weixin_4462608516 小时前
CABAL:用于追踪同行评审中合谋投标影响的多智能体仿真框架
人工智能·算法·机器学习
不会就选b16 小时前
算法日常・每日刷题--<贪心>6
数据结构·算法·leetcode