1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
public class Solution {
// 全局变量,记录递归处理到的位置
public static int where;
public static String countOfAtoms(String str) {
where = 0;
// 递归解析整个字符串
TreeMap<String, Integer> map = f(str.toCharArray(), 0);
// 构建输出结果
StringBuilder ans = new StringBuilder();
for (String key : map.keySet()) {
ans.append(key);
int cnt = map.get(key);
if (cnt > 1) { // 数量为1时不输出数字
ans.append(cnt);
}
}
return ans.toString();
}
public static TreeMap<String, Integer> f(char[] s, int i) {
TreeMap<String, Integer> ans = new TreeMap<>(); // 当前层级的总表
StringBuilder name = new StringBuilder(); // 当前正在收集的原子名称
TreeMap<String, Integer> pre = null; // 上一个括号的统计结果
int cnt = 0; // 当前收集的倍数
while (i < s.length && s[i] != ')') {
// 遇到大写字母或左括号:触发结算
if (s[i] >= 'A' && s[i] <= 'Z' || s[i] == '(') {
fill(ans, name, pre, cnt); // 将之前的内容加入总表
// 重置状态
name.setLength(0);
pre = null;
cnt = 0;
if (s[i] >= 'A' && s[i] <= 'Z') {
// 收集新的原子名称(以大写字母开头)
name.append(s[i++]);
} else {
// 遇到左括号:递归处理括号内容
pre = f(s, i + 1);
i = where + 1; // 跳过递归处理过的部分
}
}
// 小写字母:追加到原子名称
else if (s[i] >= 'a' && s[i] <= 'z') {
name.append(s[i++]);
}
// 数字:累加倍数
else {
cnt = cnt * 10 + s[i++] - '0';
}
}
// 处理最后一部分内容
fill(ans, name, pre, cnt);
where = i; // 更新全局位置,告知上层递归处理到哪里
return ans;
}
public static void fill(TreeMap<String, Integer> ans,
StringBuilder name,
TreeMap<String, Integer> pre,
int cnt) {
if (name.length() > 0 || pre != null) {
cnt = cnt == 0 ? 1 : cnt; // 没有数字默认为1
if (name.length() > 0) {
// 处理单个原子:如 H2 中的 H
String key = name.toString();
ans.put(key, ans.getOrDefault(key, 0) + cnt);
} else {
// 处理括号结果:如 (OH)2 中的 OH 表
for (String key : pre.keySet()) {
ans.put(key, ans.getOrDefault(key, 0) + pre.get(key) * cnt);
}
}
}
}
}
|