LeetCode 3090.每个字符最多出现两次的最长子字符串

题目链接

https://leetcode.cn/problems/maximum-length-substring-with-two-occurrences/

题目描述

给定一个字符串 s,找出满足每个字符最多出现两次的最长子字符串,并返回其长度。

示例

  • 输入:s = "aabba"
    • 输出:5
    • 解释:子字符串 "aabba" 中每个字符(a 和 b)最多出现两次,且长度为 5。
  • 输入:s = "aaaa"
    • 输出:2
    • 解释:最长子字符串为 "aa",每个字符最多出现两次。

解法分析:滑动窗口 + 数组计数

核心思路

本题采用滑动窗口算法,通过左右指针维护一个有效区间,确保区间内每个字符的出现次数不超过 2 次。同时,利用长度固定的数组记录字符出现的频率,实现高效的计数与判断。

代码实现

python 复制代码
class Solution:
    def maximumLengthSubstring(self, s: str) -> int:
        # 使用长度26的数组记录小写字母出现次数(假设输入仅包含小写字母)
        count = [0] * 26
        ans = left = 0
        for right in range(len(s)):
            # 计算当前字符的索引(a=0, b=1,...z=25)
            idx = ord(s[right]) - ord('a')
            count[idx] += 1  # 右指针字符计数+1
            # 当字符出现次数>2时,移动左指针收缩窗口
            while count[idx] > 2:
                left_idx = ord(s[left]) - ord('a')
                count[left_idx] -= 1  # 左指针字符计数-1
                left += 1            # 左指针右移
            # 更新最大窗口长度
            ans = max(ans, right - left + 1)
        return ans

关键逻辑解析

  1. 初始化:

    • count:长度为 26 的数组,用于记录小写字母的出现次数,假设输入仅包含小写字母。数组下标 0 对应字符 a,1 对应 b,以此类推。
    • ans:记录满足条件的最长子字符串长度,初始值为 0。
    • left:滑动窗口的左指针,初始值为 0。
  2. 右指针扩展:

    • 使用 right 从左到右遍历字符串 s。
    • 通过 ord(s[right]) - ord('a') 将字符转换为数组索引,对 count 数组中对应位置的计数加 1,表示当前字符出现次数增加。
  3. 左指针收缩:

    • 当 count[idx] > 2 时,说明当前字符在窗口内出现次数超过 2 次,需要收缩窗口。
    • 通过 ord(s[left]) - ord('a') 计算左指针指向字符的索引,将其在 count 数组中的计数减 1。
    • 左指针 left 右移一位,缩小窗口范围,直到当前字符出现次数不超过 2 次。
  4. 更新结果:

    • 每次循环中,计算当前窗口的长度 right - left + 1,并与 ans 比较,取较大值更新 ans。
    • 最终返回 ans,即满足条件的最长子字符串长度。

复杂度分析

  • 时间复杂度 : O ( n ) O(n) O(n),其中 n n n 是字符串 s 的长度。左右指针最多各遍历字符串一次,每个字符最多被处理两次。
  • 空间复杂度 : O ( 1 ) O(1) O(1),数组 count 的长度固定为 26,与输入字符串的长度无关。

优化点与注意事项

  1. 数组替代字典:使用固定长度的数组替代字典记录字符频率,避免哈希计算开销,在字符集固定(如小写字母)的场景下更高效。
  2. 字符集假设:当前代码假设输入仅包含小写字母,若字符集扩展(如包含大写字母、数字等),需要扩展数组长度或改用字典存储。
  3. 边界条件 :代码默认输入字符串非空,题目保证 s.length ≥ 2,因此无需额外处理空字符串。

总结

本解法通过滑动窗口和数组计数的结合,在 O ( n ) O(n) O(n) 时间复杂度和 O ( 1 ) O(1) O(1) 空间复杂度内高效解决问题。其核心在于利用双指针动态维护有效区间,并通过数组快速判断字符出现频率。该思路可作为处理字符频率约束类问题的通用模板,适用于更多变种题型(如每个字符最多出现 k 次)。

相关推荐
海上小飞龙2 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
ychqsq2 小时前
203.诊断
经验分享·职场和发展
青少儿编程课堂3 小时前
后缀自动机解析:本质不同子串与最长重复片段统计
c++·python·算法·bfs·信息学竞赛
朝朝辞暮i3 小时前
C++ 第 12 课:局部变量、作用域、变量生命周期
开发语言·c++·算法
乐迪信息4 小时前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉
Sirens.5 小时前
Java并发锁详解:六类锁策略与 synchronized 底层原理
java·前端·算法
和裕5 小时前
全纸结构重型纸箱能否满足 1 吨以上设备出口熏蒸豁免要求?通关合规性全解析
大数据·运维·网络·人工智能·算法
tangguofeng6 小时前
不带头结点的链队操作集(不含InitFlag)(C语言版)
算法
苏打豆7 小时前
CRISP源码阅读——基于ROS2力矩反馈控制器与速度加速度零空间
c++·线性代数·算法·矩阵·机器人
蛋蛋的就会顺顺的7 小时前
hot100——矩阵
java·数据结构·算法·leetcode·力扣