【LeetCode】726、原子的数量

【LeetCode】726、原子的数量

文章目录

  • [一、递归: 嵌套类问题](#一、递归: 嵌套类问题)
    • [1.1 递归: 嵌套类问题](#1.1 递归: 嵌套类问题)
  • 二、多语言解法


一、递归: 嵌套类问题

1.1 递归: 嵌套类问题

遇到 ( 括号, 则递归计算子问题

遇到大写字母, 或遇到 ( 括号, 则清算历史, 并开始新的记录

记录由两部分组成: 大写字母开头的 或 子函数递归的结果

go 复制代码
// go
func countOfAtoms(s string) string {
    where := 0 // 全局变量, 记录 括号内递归 的终止位置, 用于继续从此计算

    var f func(i int) map[string]int // 输入 s 的下标, 输出 哈希表, 计算括号内的 原子统计
    f = func(i int) map[string]int {
        m := map[string]int{}
        name := "" // 字母历史, 如 Mg4 的 Mg
        pre := map[string]int{} // 哈希表历史, 如 (SO3)2 的 SO3
        cnt := 0 // 次数, 如 Mg4 的 4, 如 (SO3)2 的 2
        for i < len(s) && s[i] != ')' {
            c := s[i]
            if (c >= 'A' && c <= 'Z') || c == '(' { // 需要清算历史记录, 并开始新的记录
                // 清算历史记录
                fill(m, name, pre, cnt)
                name = ""
                clear(pre)
                cnt = 0

                // 开始新的记录
                if c >= 'A' && c <= 'Z' { // 大写字母
                    name += string(c) // 通过字母得到记录
                    i++
                } else { // 左括号 (
                    pre = f(i+1) // 通过递归得到记录
                    i = where + 1 // 从递归结束的位置, 继续遍历
                }
            } else if c >= 'a' && c <= 'z' {
                name += string(c)
                i++
            } else { // 数字 c >= '0' && c <= '9'
                cnt = cnt * 10 + int(c - '0')
                i++
            }
        }
        fill(m, name, pre, cnt) // 最后一次, 比如 H2Mg3, 当遍历到整个字符串结尾时 需要触发 把 最后的 Mg3 放入结果
        where = i // 标记此递归的结束位置, 后续顶层函数继续从 where + 1 处遍历, 否则肯定死循环
        return m
    }
    m := f(0)
    return format(m)
}

// name 重复 cnt 次, 或 pre 重复 cnt 次, 添加到 m 中
func fill(m map[string]int, name string, pre map[string]int, cnt int) {
    if cnt == 0 {cnt = 1} // 如 HMF 则 遍历到 M 时, 需清算 H, 但此时 cnt 为 0, 其实是因为省略了 H1 为 H, 所以需要当 cnt == 0 时把 cnt 置为 1
    if len(name) > 0 { // 是 name 的历史
        m[name]+=cnt
    } else { // 是 pre 的历史
        for atom, count := range pre {
            m[atom]+=count*cnt
        }
    }
}

func format(m map[string]int) (ans string) {
    sli := slices.Collect(maps.Keys(m)) // 无需哈希表, 收集 keys
    slices.Sort(sli) // 排序 keys, 从而得到有序哈希表
    for _, atom := range sli {
        cnt := m[atom]
        ans += atom
        if cnt > 1 {
            ans += strconv.Itoa(cnt)
        }
    }
    return
}

参考左神: 嵌套类问题 递归思路

二、多语言解法

C p p / G o / P y t h o n / R u s t / J s / T s Cpp/Go/Python/Rust/Js/Ts Cpp/Go/Python/Rust/Js/Ts

cpp 复制代码
// cpp
go 复制代码
// go 同上
python 复制代码
# python
rust 复制代码
// rust
js 复制代码
// js
ts 复制代码
// ts
相关推荐
江畔柳前堤3 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore5 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考6 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX7 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面7 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号8 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽8 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI8 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者10 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者10 小时前
【征程6】校准量化中HistogramObserver解析
算法