726. 原子的数量

154 阅读1分钟

给你一个字符串化学式 formula ,返回 每种原子的数量 。

原子总是以一个大写字母开始,接着跟随 0 个或任意个小写字母,表示原子的名字。

如果数量大于 1,原子后会跟着数字表示原子的数量。如果数量等于 1 则不会跟数字。

  • 例如,"H2O" 和 "H2O2" 是可行的,但 "H1O2" 这个表达是不可行的。

两个化学式连在一起可以构成新的化学式。

  • 例如 "H2O2He3Mg4" 也是化学式。

由括号括起的化学式并佐以数字(可选择性添加)也是化学式。

  • 例如 "(H2O2)" 和 "(H2O2)3" 是化学式。

返回所有原子的数量,格式为:第一个(按字典序)原子的名字,跟着它的数量(如果数量大于 1),然后是第二个原子的名字(按字典序),跟着它的数量(如果数量大于 1),以此类推。

示例 1:

输入: formula = "H2O"
输出: "H2O"
解释: 原子的数量是 {'H': 2, 'O': 1}。

示例 2:

输入: formula = "Mg(OH)2"
输出: "H2MgO2"
解释: 原子的数量是 {'H': 2, 'Mg': 1, 'O': 2}。

示例 3:

输入: formula = "K4(ON(SO3)2)2"
输出: "K4N2O14S4"
解释: 原子的数量是 {'K': 4, 'N': 2, 'O': 14, 'S': 4}。

题解:

/**
 * @param {string} formula
 * @return {string}
 */
var countOfAtoms = function (formula) {
    let i = 0;
    const n = formula.length;
    const stack = [new Map()];
    while (i < n) {
        let cur = formula[i]
        // 获取原子 => 字母
        const parseAtom = () => {
            let sub = []
            sub.push(formula[i++])
            // 扫描字母后面时候有小写字母
            if (i < n && formula[i] >= 'a' && formula[i] <= 'z') {
                sub.push(formula[i++])
            }
            return sub.join('')
        }
        // 获取数字 => 数量
        const parseNum = () => {
            if (i === n || isNaN(Number(formula[i]))) {
                return 1
            }
            let num = 0;
            // 扫描数字
            while (i < n && !isNaN(Number(formula[i]))) {
                debugger
                num = num * 10 + formula[i++].charCodeAt() - '0'.charCodeAt();
            }
            return num;
        }
        if (cur == '(') {
            i++
            // 将一个空的哈希表压入栈中,准备统计括号内的原子数量
            stack.unshift(new Map())
        } else if (cur == ')') {
            i++
            // 获取括号右侧数字
            const num = parseNum();
            // 弹出括号内的原子数量
            const popMap = stack.shift();
            // 顶层原子数量
            const topMap = stack[0];
            for (const [atom, v] of popMap.entries()) {
                // 将括号内的原子数量乘上 num,加到上一层的原子数量中
                topMap.set(atom, (topMap.get(atom) || 0) + v * num);
            }

        } else {
            // 获取原子
            const atom = parseAtom();
            // 获取数字
            const num = parseNum();
            const topMap = stack[0];
            // 统计原子数量
            topMap.set(atom, (topMap.get(atom) || 0) + num);
        }
    }
    // map数据出栈
    let map = stack.pop();
    // 把map结构转为数组并排序
    map = Array.from(map).sort();
    const sb = [];
    for (const [atom, count] of map) {
        sb.push(atom);
        if (count > 1) {
            // 数字大于1跟随
            sb.push(count);
        }
    }
    return sb.join('');
};

来源:力扣(LeetCode)

链接:leetcode.cn/problems/nu…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。