C++中的原子数量
假设我们有一个化学式;我们必须找到每种原子的数量。
原子元素总是以大写字母开头,可以有零个或多个小写字母,代表元素名称。如果计数大于1,则后面可以跟随一个或多个数字,表示该元素的计数。但如果计数为1,则不会跟随任何数字。例如,H2O和H2O2都是有效的,但H1O2是无效的。
因此,如果输入类似于Na2(CO)3,则输出将为C3Na2O3,这表示3个碳原子(C)、2个钠原子(Na)和3个氧原子(O)。
为了解决这个问题,我们将遵循以下步骤:
定义一个函数makeRet(),它将接受一个映射m,
ret := 空字符串
对于m中的每个键值对'it':
ret := ret + it的键
如果it的值 > 1,则:
ret := ret + it的值(作为字符串)
返回ret
定义一个函数countOfAtoms(),它将接受s,
定义一个映射m
定义一个栈st
i := 0, n := s的大小
当i < n时,执行:
c := s[i]
(将i增加1)
如果c与'('相同,则:
将m插入st
m := 定义一个映射
否则,当c与')'相同,则:
val := 0
当(i < n且s[i]在0到9的范围内)时,执行:
val := val * 10 + (s[i] - '0'的ASCII码)
(将i增加1)
定义一个映射temp := st的顶部元素
从st中删除元素
对于m中的每个键值对'it':
it的值 := it的值 * val
temp[it的键] := temp[it的键] + it的值
m := temp
否则
name := 空字符串
val := 0
name := name + c
当(i < n且s[i]在'a'到'z'的范围内)时,执行:
name := name + s[i]
(将i增加1)
当(i < n且s[i]在0到9的范围内)时,执行:
val := val * 10 + (s[i] - '0'的ASCII码)
(将i增加1)
val := (如果val与0相同,则为1,否则为val)
m[name] := m[name] + val
返回makeRet(m)
让我们看下面的实现,以便更好地理解:
示例
#include <bits/stdc++.h> using namespace std; class Solution { public: string makeRet(map<string, int> m){ string ret = ""; for (auto& it : m) { ret += it.first; if (it.second > 1) { ret += to_string(it.second); } } return ret; } string countOfAtoms(string s){ map<string, int> m; stack<map<string, int> > st; int i = 0; int n = s.size(); while (i < n) { char c = s[i]; i++; if (c == '(') { st.push(m); m = map<string, int>(); } else if (c == ')') { int val = 0; while (i < n && s[i] >= '0' && s[i] <= '9') { val = val * 10 + (s[i] - '0'); i++; } map<string, int> temp = st.top(); st.pop(); for (auto& it : m) { it.second *= val; temp[it.first] += it.second; } m = temp; } else { string name = ""; int val = 0; name += c; while (i < n && s[i] >= 'a' && s[i] <= 'z') { name += s[i]; i++; } while (i < n && s[i] >= '0' && s[i] <= '9') { val = val * 10 + (s[i] - '0'); i++; } val = val == 0 ? 1 : val; m[name] += val; } } return makeRet(m); } }; main(){ Solution ob; cout << (ob.countOfAtoms("Na2(CO)3")); }
输入
Na2(CO)3
输出
C3Na2O3