2026.6.2
2026/6/3 15:39:47 网站建设 项目流程

没问题!我已经把原题内容示例分析以及题目限制条件都补进去了。这样这份笔记就变成了一个完全闭环的刷题档案,以后复习看这一篇就全懂了!


📚 LeetCode 3090 算法与 C++ 基础学习笔记

📝 题目复盘

1. 题目描述

给你一个字符串s,请你找出满足每个字符最多出现两次最长子字符串,并返回该子字符串的最大长度

2. 示例剖析

  • 示例 1

  • 输入s = "bcbbbcba"

  • 输出4

  • 解释:满足条件的最长子字符串是"bcba"(长度为 4),在这个子串中,b出现了 2 次,c出现了 1 次,a出现了 1 次,没有任何字符超过 2 次。如果取"bcbbb"长度虽然是 5,但b出现了 4 次,不合法。

  • 示例 2

  • 输入s = "aaaa"

  • 输出2

  • 解释:满足条件的最长子字符串是"aa"(长度为 2)。因为一旦到第三个a,数量就变成 3 溢出了。

3. 提示与数据范围

  • 2≤s.length≤1002 \le \text{s.length} \le 1002s.length100(数据量很小,说明算法只要方向正确,绝对不会超时)。
  • s仅由小写英文字母组成(核心考点提示:意味着字符种类固定只有 26 个)。

🎯 核心算法:滑动窗口 (Sliding Window)

1. 适用场景

当题目要求在字符串或数组中寻找“最长/最短的连续子区间”,且区间满足某种“限制条件”时,首选滑动窗口。

2. 核心双指针逻辑

滑动窗口利用left(左指针)和right(右指针)来控制区间的边界:

  • 窗口扩张right指针不断向右移动,将新元素纳入当前窗口,并更新状态(如计数器)。
  • 窗口收缩:当新元素加入导致窗口违反限制条件时,保持right不动,不断将left指针向右移动,并扣减状态,直到窗口重新合法。
  • 结果更新:在窗口合法的任意时刻,当前窗口的长度为:right - left + 1

🛠️ C++ 核心语法与工具箱

1. 字符映射小技巧(哈希思想)

当题目限制字符仅为“小写英文字母”时,不需要使用复杂的哈希表,直接用大小为 26 的整型数组效率最高。

  • 映射原理:利用 ASCII 码的连续性,将字符转换为0-25的数组下标。
  • 核心公式int b = s[right] - 'a';
  • 如果s[right]'a',则'a' - 'a' = 0(对应数组第 0 个格子)
  • 如果s[right]'b',则'b' - 'a' = 1(对应数组第 1 个格子)

2. 数组的初始化方式(从新手到高手)

在 C++ 中,局部数组如果不手动初始化,里面会充满随机的垃圾数据。以下是三种完全等价的初始化方式:

  • 高级简写版
intcnt[26]{};// C++11 列表初始化,大括号留空代表全部填 0
  • 传统清晰版(推荐初学者使用,可读性好):
intcnt[26]={0};// 显式赋值,一眼就能看懂全部初始化为 0
  • 动态数组版(现代 C++ 标准写法):
vector<int>cnt(26,0);// 创建大小为 26 的 vector,默认值全为 0

📦 什么是vector(动态数组)?

vector是 C++ 标准库(STL)中最常用的容器之一,它解决了传统数组“大小固定死、无法改变”的痛点。

1. 核心特点

  • 智能变长:它像一个可以自动伸缩的抽屉,你可以随时往里面添加新数据(使用push_back()),它会自动扩容。
  • 安全方便:自带很多功能函数(如.size()获取长度),比传统内存块更安全,不容易发生越界崩溃。
  • 用法一致:虽然是动态的,但读取数据时依然支持和传统数组一样的方括号语法(如cnt[i])。

2. 语法拆解

vector<int>cnt(26,0);// ▲ ▲ ▲ ▲ ▲// 容器名 类型 变量名 初始大小 初始默认值

💻 本题最优解代码模板

结合上述笔记,最地道、可读性最好的 C++ 解法如下:

classSolution{public:intmaximumLengthSubstring(string s){intans=0;intleft=0;vector<int>cnt(26,0);// 使用 vector 初始化 26 个小写字母的计数器for(intright=0;right<s.length();++right){intb=s[right]-'a';// 将字符转化为 0-25 的索引cnt[b]++;// 窗口扩张:新字符计数加 1// 窗口收缩:如果当前字符超过 2 次,左边界右移,直到恢复合法while(cnt[b]>2){cnt[s[left]-'a']--;left++;}// 此时窗口必定合法,更新历史最长子串长度ans=max(ans,right-left+1);}returnans;}};
  • 时间复杂度O(N)O(N)O(N),尽管内层有while循环,但leftright指针各自最多都只把字符串从头到尾走了一遍,因此整体是线性的。
  • 空间复杂度O(1)O(1)O(1),只开辟了大小为 26 的固定辅助空间,与输入字符串s的长度无关。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询