当前位置: 首页 > news >正文

千问 LeetCode 2949. 统计美丽子字符串 II Go实现

这道题用 Go 来实现,不仅代码会更简洁,运行效率也会非常高。核心思路依然是“前缀和 + 哈希表”,我们只需要把 Java 的逻辑平滑地转换成 Go 的语法习惯即可。

核心思路回顾
1. 数学转化:子字符串要美丽,元音和辅音数量必须相等(各占一半,设长度为 L,则各为 L/2)。且 (L/2 * L/2) % k == 0。我们需要算出满足这个条件的最小子字符串长度周期 mod。
2. 前缀和 + 哈希表:遍历时,元音记为 +1,辅音记为 -1。如果两个位置的前缀和相等,且它们的下标差是 mod 的倍数,那么这段子字符串就是“美丽”的。我们用哈希表记录 (前缀和, 下标%mod) 出现的次数。

Go 代码实现

func beautifulSubstrings(s string, k int) int64 {
// 1. 计算满足 (L/2)^2 % k == 0 的最小周期长度 mod
mod := getMod(k)

var ans int64 = 0
sum := 0 // 前缀和:元音+1,辅音-1

// 2. 哈希表记录状态 (前缀和, 下标 % mod) 出现的次数
// Go 中可以用 map[[2]int]int 或者 map[string]int 作为复合键
// 这里使用 [2]int 数组作为 key,性能更好且更符合 Go 习惯
mapState := make(map[[2]int]int)

// 初始状态:前缀和为0,虚拟下标为 -1。
// (-1) % mod 在 Go 中结果为负数,需要处理为 mod - 1
mapState[[2]int{mod - 1, 0}] = 1

for i := 0; i < len(s); i++ {
c := s[i]
// 遇到元音+1,辅音-1
if c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' {
sum++
} else {
sum--
}

// 当前状态的下标余数
remainder := i % mod
key := [2]int{remainder, sum}

// 如果之前出现过相同的状态,说明中间这段子字符串满足条件
ans += int64(mapState[key])

// 更新当前状态的出现次数
mapState[key]++
}

return ans
}

// 对 4*k 进行质因数分解,求出满足 x^2 % (4*k) == 0 的最小 x
func getMod(k int) int {
m := 4 * k
mod := 1
for i := 2; i*i <= m; i++ {
if m%i == 0 {
cnt := 0
for m%i == 0 {
m /= i
cnt++
}
// 如果质因数的次数是奇数,需要多乘一个 i 保证平方后能被整除
// (cnt + 1) / 2 等价于向上取整 cnt / 2
power := (cnt + 1) / 2
for j := 0; j < power; j++ {
mod *= i
}
}
}
// 处理剩下的最大质因数
if m > 1 {
mod *= m
}
return mod
}

Go 实现的细节亮点
1. 复合键的使用:在 Java 中我们通常把两个数拼成字符串 remainder + "," + sum 当作 Key。而在 Go 中,我们可以直接使用固定长度的数组 [2]int{remainder, sum} 作为 Map 的键,不仅写起来清爽,底层的哈希计算效率也更高。
2. 负数取模处理:Go 语言中,-1 % 5 的结果是 -1(而在 Java/Python 中可能是 4)。所以我们在初始化哈希表时,需要手动将虚拟下标 -1 的余数处理为 mod - 1。
3. 类型转换:题目要求返回 int64,在累加结果时记得把 map 中取出的 int 强转为 int64。

复杂度分析
* 时间复杂度:O(n + sqrt(k))。遍历字符串 O(n),计算 mod 质因数分解 O(sqrt(k))。
* 空间复杂度:O(n)。哈希表最多存储 n 个状态。

http://www.cnnetsun.cn/news/2717360.html

相关文章:

  • 千问 LeetCode 2953. 统计完全子字符串 Java实现
  • Havenlon 的共同治理哲学:Owner 不应该天然拥有最终执行权
  • 从质检到金融风控:假设检验的7个真实业务场景拆解(含Python/R代码片段)
  • 如何快速掌握通达信金融数据:mootdx新手的完整入门指南
  • 紧急升级通知:Lindy v2.8.3已修复3个高危资源漂移漏洞——你的自动化流水线是否仍在裸奔?
  • 腾讯云杀疯了:大模型降价 97.5%,小玩家正在出局
  • yuzu模拟器下载安装全攻略:告别卡顿的终极优化指南
  • 抖音批量下载神器:5分钟学会保存所有精彩内容
  • 避开重映射的坑:雅特力AT32F413 TMR3通道2输出PWM的另一种配置思路(附完整代码)
  • 告别定位失败!Selenium处理shadowDOM的两种“抄近道”方法(含Chrome DevTools技巧)
  • 推挽变换器的基本结构
  • 免费提取文字软件保姆级指南:2026年最推荐的5种方法一看就会
  • 半导体与机器人行业利润大增:是真实需求驱动,还是短期扰动?
  • 麒麟V10 SP3/SP2系统yum源配置保姆级教程(附官方源地址与常见错误排查)
  • 3分钟解锁所有加密音乐:Unlock-Music终极免费解决方案
  • Win10/Win11升级后C盘少了10个G?教你彻底清理“以前的Windows安装”并释放空间
  • 搜索进入 Agentic 智能体时代,内容要能 “被 AI 直接用”
  • 别再硬编码了!用PFC2D 5.0模拟滑坡,这份参数调试与结果分析指南请收好
  • SpaceX拟6月纳斯达克上市,估值1.75 - 2万亿美元,AI与星链业务暗藏哪些风险?
  • 鸣潮自动化终极指南:3大场景解锁智能挂机新体验
  • ComfyUI-VideoHelperSuite:视频处理中的零除错误防御与智能帧选择技术
  • 洛雪音乐音源完整配置指南:5步打造你的专属高品质音乐库
  • 基于Arduino与步进电机的桌面摩天轮DIY:从机械结构到编程控制
  • 别再死记硬背公式了!用‘辗转相除法’手把手带你搞定GCD和LCM(附Java代码实战)
  • 逆推思维:找到达成目标的最短路线
  • 5分钟快速上手!MediaCrawler跨平台数据采集工具终极指南
  • DIY超级英雄控制台:从自闪LED到Arduino的创客实践
  • 低代码平台 表单设计器 unione form editor 功能组件 —— 按钮组件
  • 树莓派与Phidgets改造万圣节装饰:超声波感应与继电器控制实战
  • 【文档检索提效】实战指南:用 LangChain + FAISS 搭建你的本地 API 文档问答机器人