给出一个字符串格式的化学分子式,计算原子的个数
每个化学元素都是由一个大写字母,或者一个大写字母后跟着若干个小写字母组成,例如H是一个化学元素,Mg也是一个化学元素。
每个分子式中,原子的个数写在元素后面,如果原子个数是1,那么原子个数省略。例如H2O和H2O2都是有效的分子式,但H1O2不是有效分子式。
每个分子式中包含若干括号,为简单起见,分子式中只有小括号。
每次输入一个分子式,对每个给定的分子式,求出每个原子的个数,按照原子字母表的顺序排列,并输出。
一行,一个字符串表示输入的分子式
按要求输出答案
H2O
H2O
Mg(OH)2
H2MgO2
K4(ON(SO3)2)2
K4N2O14S4
import java.util.*;
// 栈 + Map计数
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.next();
char[] c = s.toCharArray();
Deque<Map<String, Integer>> stack = new LinkedList<>();
int n = c.length;
for (int i = 0; i < n;) {
if (Character.isUpperCase(c[i])) {
int j = i + 1;
while (j < n && Character.isLowerCase(c[j])) j++;
String key = s.substring(i, j);
int num = 0;
while (j < n && Character.isDigit(c[j])) {
num = num * 10 + c[j] - '0';
j++;
}
i = j;
num = num == 0 ? 1 : num;
Map<String, Integer> map = new HashMap<>();
map.put(key, num);
stack.push(map);
} else if (c[i] == '(') {
Map<String, Integer> map = new HashMap<>();
map.put("(", -1);
stack.push(map);
i++;
} else { // 遇到 ) 要合并 () 里面的并找到与之匹配的 (
int num = 0, j = i + 1;
while (j < n && Character.isDigit(c[j])) {
num = num * 10 + c[j] - '0';
j++;
}
i = j;
num = num == 0 ? 1 : num;
Map<String, Integer> map = new HashMap<>();
while (!stack.peek().containsKey("(")) {
Map<String, Integer> mp = stack.pop();
for (String key : mp.keySet()) {
map.merge(key, mp.get(key) * num, Integer::sum);
}
}
stack.pop();
stack.push(map);
}
}
Map<String, Integer> map = new HashMap<>(); // 合并栈内剩余的
while (!stack.isEmpty()) {
Map<String, Integer> mp = stack.pop();
for (String key : mp.keySet()) {
map.merge(key, mp.get(key), Integer::sum);
}
}
List<String> list = new ArrayList<>(map.keySet()); // 字典序
Collections.sort(list);
StringBuilder sb = new StringBuilder();
for (String key : list) {
sb.append(key);
int val = map.get(key);
if (val > 1) sb.append(val);
}
System.out.println(sb.toString());
}
}