【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)。
相关推荐
GoAI2 小时前
DeepSeek Harness Memory (一)主流记忆插件总结
后端·算法·面试
Pniubi3 小时前
力扣54.螺旋矩阵
算法·leetcode·矩阵
choumou_M5 小时前
算法_1:由浅入深学习快速排序QuickSort
学习·算法·排序算法
Coder_Shenshen6 小时前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
心仪久了会沦陷8 小时前
C语言数据结构入门——树与二叉树详解:概念、堆实现与链式遍历
c语言·数据结构·算法
小此方8 小时前
[算法实战论:动态规划]背包问题概念,01不满背包问题,01满背包问题,背包问题的滚动数组空间优化
算法·动态规划
悠仁さん9 小时前
【C++】哈希表
c++·算法·散列表
地平线开发者9 小时前
点云算法整理与常用计算模块:从数据到模型,再到工程与量化
算法·自动驾驶
武子康12 小时前
H3-World 为何在加载 LoRA 前,先检查导入的代码?
人工智能·深度学习·算法