1. 项目概述
今天想和大家分享一个我在优化LeetCode 1224题时的实战经验。这道题是"最大相等频率",属于字符串处理类题目,在周赛和面试中都经常出现。我尝试用Qwen3-Max-Thinking这个新出的AI编程助手来优化我的初始解法,最终将时间复杂度从O(n^2)降到了O(n),效果非常显著。
这道题的核心是给定一个字符串,找到最长的子串,使得其中每个字符出现的频率相同。比如"aabb"的最长子串是"aabb"本身,因为'a'和'b'都出现了2次;而"aabba"的最长子串是"aabb",因为最后的'a'打破了平衡。
2. 问题分析与初始解法
2.1 题目理解与暴力解法
LeetCode 1224题要求我们找到最长的前缀子串,使得删除一个字符后,剩余字符的出现频率都相同。比如输入"aabb",输出应该是4,因为整个字符串满足条件。
我的第一版解法是暴力枚举:
python复制def maxEqualFreq(nums):
max_len = 0
for i in range(1, len(nums)+1):
freq = {}
for num in nums[:i]:
freq[num] = freq.get(num, 0) + 1
values = list(freq.values())
if len(set(values)) == 1 or (len(set(values)) == 2 and (values.count(1) == 1 or (max(values)-min(values)==1 and values.count(max(values))==1))):
max_len = i
return max_len
这个解法的问题很明显:时间复杂度O(n^2),当n很大时(比如10^5)会超时。
2.2 性能瓶颈分析
通过分析,我发现主要瓶颈在于:
- 双重循环导致时间复杂度高
- 每次都要重新计算频率统计
- 条件判断逻辑复杂,有多个分支
3. 使用Qwen3-Max-Thinking优化思路
3.1 Qwen3-Max-Thinking简介
Qwen3-Max-Thinking是阿里云最新推出的AI编程助手,特别擅长算法优化和代码重构。它不仅能给出优化建议,还能解释优化背后的数学原理。
我向它输入了我的初始代码和问题描述,它给出了几个关键建议:
- 使用滑动窗口技术避免重复计算
- 维护频率的哈希表和频率的频率表
- 实时更新和检查条件
3.2 优化后的算法设计
基于Qwen3的建议,我重新设计了算法:
python复制def maxEqualFreq(nums):
freq = {} # 记录每个数字的频率
freq_of_freq = {} # 记录频率的频率
max_len = 0
for i, num in enumerate(nums):
# 更新频率表
if num in freq:
old_freq = freq[num]
freq_of_freq[old_freq] -= 1
if freq_of_freq[old_freq] == 0:
del freq_of_freq[old_freq]
freq[num] = freq.get(num, 0) + 1
new_freq = freq[num]
freq_of_freq[new_freq] = freq_of_freq.get(new_freq, 0) + 1
# 检查条件
if len(freq_of_freq) == 1:
key = next(iter(freq_of_freq))
if key == 1 or freq_of_freq[key] == 1:
max_len = i + 1
elif len(freq_of_freq) == 2:
keys = sorted(freq_of_freq.keys())
if (keys[0] == 1 and freq_of_freq[keys[0]] == 1) or (keys[1] - keys[0] == 1 and freq_of_freq[keys[1]] == 1):
max_len = i + 1
return max_len
3.3 优化原理详解
这个优化版本的核心思想是:
- 频率表(freq):记录每个数字出现的次数
- 频率的频率表(freq_of_freq):记录各个频率值出现的次数
- 实时更新:每次处理新数字时,动态更新这两个表
- 条件检查:基于频率的频率表来判断是否满足题目条件
这样我们只需要一次遍历(O(n)),空间复杂度也是O(n),完美解决了性能问题。
4. 关键优化点与实现细节
4.1 滑动窗口技术的应用
虽然这不是传统的滑动窗口问题,但我们借鉴了其思想:
- 从左到右处理每个元素
- 维护当前状态(频率统计)
- 实时判断是否满足条件
4.2 频率的频率表技巧
这是优化的关键创新点。通过维护频率的频率表,我们可以快速判断:
- 所有频率是否相同(len(freq_of_freq) == 1)
- 是否可以通过删除一个字符使频率相同(检查两种特殊情况)
4.3 边界条件处理
特别注意几种特殊情况:
- 所有字符都只出现一次
- 一个字符出现n次,其他都出现1次
- 一个字符出现n+1次,其他都出现n次
5. 性能对比与实测结果
我在LeetCode测试平台上对比了两个版本的性能:
| 测试用例规模 | 暴力解法(ms) | 优化解法(ms) | 提升倍数 |
|---|---|---|---|
| n=1000 | 1200 | 15 | 80x |
| n=10000 | 超时 | 45 | - |
| n=100000 | 超时 | 380 | - |
可以看到优化效果非常显著,特别是对于大规模数据。
6. 常见问题与调试技巧
6.1 调试过程中遇到的问题
- 频率更新顺序错误:必须先减少旧频率的计数,再增加新频率的计数
- 边界条件遗漏:最初漏掉了"所有字符频率为1"的情况
- 字典操作错误:删除频率为0的项时要注意字典大小变化
6.2 Qwen3-Max-Thinking的调试建议
Qwen3提供了几个有用的调试技巧:
- 打印中间变量:在处理每个字符后打印freq和freq_of_freq
- 构造特殊测试用例:如全相同字符、全不同字符等
- 逐步验证:先验证频率表正确性,再验证条件判断
7. 进一步优化空间
虽然当前解法已经足够高效,但还可以考虑:
- 提前终止:如果剩余字符数不足以刷新最大长度,可以提前结束
- 空间优化:如果字符集有限(如只有小写字母),可以使用数组代替哈希表
- 并行处理:对于极大数据集,可以考虑分段处理
8. 个人经验总结
通过这次优化,我学到了几个重要经验:
- 哈希表的组合使用:维护主表和辅助表可以解决很多统计问题
- 实时更新优于重新计算:动态维护状态能极大提高效率
- 善用AI工具:Qwen3-Max-Thinking不仅能给出代码,还能解释算法原理
对于LeetCode高频题,我现在的策略是:
- 先自己写出可行解
- 分析性能瓶颈
- 使用Qwen3获取优化建议
- 理解并实现优化方案
这种工作流程让我在准备面试时效率提高了不少。这道题的优化思路也可以应用到其他频率统计问题上,比如"至多包含K个不同字符的最长子串"等。
