原子的数量

07/05/2021

leetcode-原子的数量

题目描述

给你一个字符串化学式 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}。

提示:

  • 1 <= formula.length <= 1000
  • formula 由英文字母、数字、'(' 和 ')' 组成
  • formula 总是有效的化学式

本人题解

/**
 * @param {string} formula
 * @return {string}
 */
 var countOfAtoms = function(formula) {
    function isLower(c) {
      return c >= 'a' && c <= 'z' 
    }
    function isNum(n) {
      return n >= '0' && n <= '9'
    }
    let o = {mul: 1}, loops = [o], atom = '', count = '', result = {};
    formula.split('').forEach(i => {
      if (isNum(i)) {
        count = count + i;
      } else if (isLower(i)) {
        atom = atom + i
      } else if (i == '(') {
        setAtom();
        let curLoop = loops[loops.length-1]
        curLoop.subs = curLoop.subs || []
        let nextLoop = {}
        curLoop.subs.push(nextLoop)
        loops.push(nextLoop)
      } else if (i == ')') {
        setAtom();
        loops.pop();
      } else {
        setAtom();
        atom = i;
      }
    })
    setAtom();
    function setAtom() {
      if (!atom && !count) {
        // do nothing
      } else if (!atom) {
        let parLoop = loops[loops.length-1]
        let curLoop = parLoop.subs[parLoop.subs.length-1]
        curLoop.mul = +count
      } else {
        let curLoop = loops[loops.length - 1]
        curLoop[atom] = (curLoop[atom] || 0) + (+count || 1)
      }
      atom = count = '';
    }
    function loopAll(loop) {
      let mul = loop.mul, subs = loop.subs || [];
      delete loop.mul; delete loop.subs;
      Object.keys(loop).forEach(i => {
        result[i] = (result[i] || 0) + loop[i] * mul
      })
      subs.forEach(s => {
        s.mul = (s.mul || 1) * mul;
        loopAll(s)
      })
    }
    loopAll(o)
    let resultS = ''
    Object.keys(result).sort((a,b) => {
        if (a[0] != b[0]) {
            return a[0] > b[0] ? 1 : -1
        } else {
            if (!!a[1] && !!b[1]) {
                return a[1] > b[1] ? 1 : -1
            } else {
                return a[1] ? 1 : -1
            }
        }
    }).forEach(i => {
      resultS += i
      if (result[i] !== 1) {
        resultS += result[i]
      }
    })
    return resultS
  };

2025-03-14

/**
 * @param {string} formula
 * @return {string}
 */
var countOfAtoms = function(formula) {
    let result = {}, stack = [], curAtom = '', curNum = '', stackPop = undefined;
 
    function setAtom() {
      if (curAtom) {
        if (stack.length > 0) {
          const last = stack[stack.length - 1];
          last[curAtom] = (last[curAtom] || 0) + (curNum ? parseInt(curNum) : 1);
        } else {
          result[curAtom] = (result[curAtom] || 0) + (curNum ? parseInt(curNum) : 1);
        }
        curAtom = '';
        curNum = '';
      } else if (stackPop) {
        if (stack.length > 0) {
          const last = stack[stack.length - 1];
          Object.keys(stackPop).forEach(key => {
            last[key] = (last[key] || 0) + stackPop[key] * (curNum ? parseInt(curNum) : 1);
          })
        } else {
          Object.keys(stackPop).forEach(key => {
            result[key] = (result[key] || 0) + stackPop[key] * (curNum ? parseInt(curNum) : 1);
          })
        }
        stackPop = undefined;
        curNum = '';
      }
    }
    formula.split('').forEach(c => {
      if (c === '(') {
        setAtom()
        stack.push({})
      } else if (c === ')') {
        setAtom()
        stackPop = stack.pop();
      } else if (c >= '0' && c <= '9') {
        curNum += c;
      } else if (c >= 'A' && c <= 'Z') {
        setAtom()
        curAtom += c;
      } else if (c >= 'a' && c <= 'z') {
        curAtom += c;
      }
    })
    setAtom()
    return Object.keys(result).sort().map(key => `${key}${result[key] > 1 ? result[key] : ''}`).join('');
};

分析

忘了。以后再补