给你一个字符串化学式 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 总是有效的化学式
递归处理,遇到括号压栈,括号结束出栈,并计算括号内的原子数:
cpp
class Solution {
public:
string countOfAtoms(string formula) {
stack<map<string, int>> stk;
map<string, int> curCnt;
string curName = "";
int curNum = 0;
for (int i = 0; i < formula.size(); ++i) {
char c = formula[i];
// 遇到新的元素,或遇到括号时,说明处理完一个元素了
if (isupper(c) || c == '(' || c == ')') {
// 将得到的元素和数量计入答案
if (!curName.empty()) {
curNum = max(1, curNum);
curCnt[curName] += curNum;
}
curName = "";
curNum = 0;
}
// 遇到左括号,入栈当前层的原子及其数量
if (c == '(') {
stk.push(curCnt);
curCnt.clear();
}
// 遇到右括号
if (c == ')') {
// 看括号内的集合会重复几次
++i;
int num = 0;
while (i < formula.size() && isdigit(formula[i])) {
num = num * 10 + (formula[i] - '0');
++i;
}
num = max(num, 1);
// 括号内的原子数量重复num次
for (auto &p : curCnt) {
p.second *= num;
}
// 上一层的原子数量也加到结果里
for (auto &p : stk.top()) {
curCnt[p.first] += p.second * num;
}
stk.pop();
--i;
}
if (isalpha(c)) {
curName.push_back(c);
} else if (isdigit(c)) {
curNum = curNum * 10 + (c - '0');
}
if (i == formula.size() - 1) {
if (!curName.empty()) {
curNum = max(1, curNum);
curCnt[curName] += curNum;
}
}
}
string res;
for (auto p : curCnt) {
res += p.first;
if (p.second != 1) {
res += to_string(p.second);
}
}
return res;
}
};
如果formula的长度为n,则此算法时间复杂度为O(n2^22),首先遍历formula的时间是n,最差情况下,即尽可能多层嵌套时,如(B(C(D)n1)n2)n3,此时curCnt最多只会有一个原子,出栈时也只会有1个原子,但出栈阶段curCnt会线性增长到O(n)级别,每次出栈都会遍历curCnt,让curCnt的每个原子重复括号后的数字次,因此内层循环也需要O(n)时间;空间复杂度为O(n),因为stk的最大深度是O(n)级别。