leet-code/src/main/java/leetcode/editor/cn/NumberOfAtoms.java
huangge1199@hotmail.com 6b6f3cd2d6 726:原子的数量
2021-07-05 21:49:02 +08:00

147 lines
4.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//给定一个化学式formula作为字符串返回每种原子的数量。
//
// 原子总是以一个大写字母开始接着跟随0个或任意个小写字母表示原子的名字。
//
// 如果数量大于 1原子后会跟着数字表示原子的数量。如果数量等于 1 则不会跟数字。例如H2O 和 H2O2 是可行的,但 H1O2 这个表达是不可行的。
//
//
// 两个化学式连在一起是新的化学式。例如 H2O2He3Mg4 也是化学式。
//
// 一个括号中的化学式和数字(可选择性添加)也是化学式。例如 (H2O2) 和 (H2O2)3 是化学式。
//
// 给定一个化学式 formula ,返回所有原子的数量。格式为:第一个(按字典序)原子的名字,跟着它的数量(如果数量大于 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}。
//
//
// 示例 4
//
//
//输入formula = "Be32"
//输出:"Be32"
//
//
//
//
// 提示:
//
//
// 1 <= formula.length <= 1000
// formula 由小写英文字母、数字 '(' 和 ')' 组成。
// formula 是有效的化学式。
//
// Related Topics 栈 哈希表 字符串
// 👍 188 👎 0
package leetcode.editor.cn;
import java.util.*;
//726:原子的数量
class NumberOfAtoms {
public static void main(String[] args) {
//测试代码
Solution solution = new NumberOfAtoms().new Solution();
}
//力扣代码
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
int i, n;
String formula;
public String countOfAtoms(String formula) {
this.i = 0;
this.n = formula.length();
this.formula = formula;
Deque<Map<String, Integer>> stack = new LinkedList<Map<String, Integer>>();
stack.push(new HashMap<String, Integer>());
while (i < n) {
char ch = formula.charAt(i);
if (ch == '(') {
i++;
stack.push(new HashMap<String, Integer>()); // 将一个空的哈希表压入栈中,准备统计括号内的原子数量
} else if (ch == ')') {
i++;
int num = parseNum(); // 括号右侧数字
Map<String, Integer> popMap = stack.pop(); // 弹出括号内的原子数量
Map<String, Integer> topMap = stack.peek();
for (Map.Entry<String, Integer> entry : popMap.entrySet()) {
String atom = entry.getKey();
int v = entry.getValue();
topMap.put(atom, topMap.getOrDefault(atom, 0) + v * num); // 将括号内的原子数量乘上 num加到上一层的原子数量中
}
} else {
String atom = parseAtom();
int num = parseNum();
Map<String, Integer> topMap = stack.peek();
topMap.put(atom, topMap.getOrDefault(atom, 0) + num); // 统计原子数量
}
}
Map<String, Integer> map = stack.pop();
TreeMap<String, Integer> treeMap = new TreeMap<String, Integer>(map);
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {
String atom = entry.getKey();
int count = entry.getValue();
sb.append(atom);
if (count > 1) {
sb.append(count);
}
}
return sb.toString();
}
public String parseAtom() {
StringBuffer sb = new StringBuffer();
sb.append(formula.charAt(i++)); // 扫描首字母
while (i < n && Character.isLowerCase(formula.charAt(i))) {
sb.append(formula.charAt(i++)); // 扫描首字母后的小写字母
}
return sb.toString();
}
public int parseNum() {
if (i == n || !Character.isDigit(formula.charAt(i))) {
return 1; // 不是数字,视作 1
}
int num = 0;
while (i < n && Character.isDigit(formula.charAt(i))) {
num = num * 10 + formula.charAt(i++) - '0'; // 扫描数字
}
return num;
}
}
//leetcode submit region end(Prohibit modification and deletion)
}