原子的数量
07/05/2021
题目描述
给你一个字符串化学式 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('');
};分析
忘了。以后再补