【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)。
相关推荐
劈星斩月3 分钟前
监督学习算法 之 决策树
学习·算法·决策树
学计算机的计算基7 分钟前
操作系统内存管理全解:虚拟内存、页表、COW、malloc、OOM一篇搞定
java·笔记·算法
tachibana212 分钟前
hot100 前 K 个高频元素(347)
java·数据结构·算法·leetcode
To_OC8 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
旖-旎9 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
To_OC10 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
delishcomcn10 小时前
AI视觉识别+分切算法:电化铝缺陷检测与裁切一体化解锁
人工智能·算法
触底反弹11 小时前
深入理解大模型采样:Temperature、Top-K、Top-P 的原理与实战
人工智能·算法·面试
雪碧聊技术11 小时前
力扣 LCR 091. 粉刷房子 —— 动态规划入门详解
算法·动态规划