题目描述:
给定一个化学式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}。
注意:
所有原子的第一个字母为大写,剩余字母都是小写。
formula的长度在[1, 1000]之间。
formula只包含字母、数字和圆括号,并且题目中给定的是合法的化学式。
用传统思路写:
代码:明显会超时
import java.util.Map.Entry;
import java.util.Stack;
import java.util.TreeMap;
class Solution {
public String countOfAtoms(String formula) {
Stack<Character> stack = new Stack<>();
char tem[] = formula.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < tem.length;) {
char c = tem[i];
if(c == ')'){
StringBuilder tem1 = new StringBuilder();
while (!stack.isEmpty() && stack.peek() != '(') {
tem1.append(stack.pop());
}
stack.pop();
int [] get = gettime(formula, i + 1);
i = get[1];
int time = get[0] - 1;
StringBuilder tem2 = new StringBuilder(tem1);
for (int j = 0; j < time; j++) {
tem1.append(tem2);
}
for (int j = tem1.length() - 1; j >= 0; j--) {
stack.push(tem1.charAt(j));
}
}else {
stack.push(c);
i++;
}
}
StringBuilder sBuilder = new StringBuilder();
while (!stack.isEmpty()) {
sBuilder.append(stack.pop());
}
TreeMap<String, Integer> map = new TreeMap<>();
sBuilder.reverse();
int start = 0;
for (int i = 0; i < sBuilder.length();) {
char c = sBuilder.charAt(i);
if(i == sBuilder.length() - 1){
int [] gets = gettime(sBuilder.toString(), i + 1);
i = gets[1];
int time = gets[0];
map.put(c + "", map.getOrDefault(c + "", 0) + time);
}else {
if(sBuilder.charAt(i + 1) >= 'a' && sBuilder.charAt(i + 1) <= 'z'){
String str = c + "" +sBuilder.charAt(i + 1) + "";
int [] gets = gettime(sBuilder.toString(), i + 2);
i = gets[1];
int time = gets[0];
map.put(str, map.getOrDefault(str, 0) + time);
}else {
int [] gets = gettime(sBuilder.toString(), i + 1);
i = gets[1];
int time = gets[0];
map.put(c + "", map.getOrDefault(c + "", 0) + time);
}
}
}
StringBuilder result = new StringBuilder();
for (Entry<String, Integer> c : map.entrySet()) {
result.append(c.getKey());
if(c.getValue() == 1){
continue;
}else {
result.append(c.getValue());
continue;
}
}
return result.toString();
}
public int[] gettime(String str,int index){
int tem = index;
while (index < str.length() && str.charAt(index) <= '9' &&
str.charAt(index) >= '0') {
index ++;
}
if(index == tem){
return new int[]{1,index};
}
return new int[]{Integer.valueOf(str.substring(tem, index)),index};
}
}
参考别人的思路,哎
整了半天还超时
LeetCode 原子的数量(递归+hash表)
参考别人的思路解法
public String countOfAtoms(String formula) {
if (!formula.contains("(")) {
TreeMap<String, Integer> map = new TreeMap<>();
String atom = "";
int len = 0;
char[] chars = formula.toCharArray();
atom = "" + chars[0];
for (int i = 1; i < chars.length; i++) {
if (Character.isUpperCase(chars[i])) {
len = len == 0 ? 1 : len;
if (map.containsKey(atom)) {
map.put(atom, map.get(atom) + len);
} else {
map.put(atom, len);
}
len = 0;
atom = "" + chars[i];
continue;
}
if (Character.isLowerCase(chars[i])) {
atom += chars[i];
continue;
}
len = len * 10 + Character.getNumericValue(chars[i]);
}
len = len == 0 ? 1 : len;
if (map.containsKey(atom)) {
map.put(atom, map.get(atom) + len);
} else {
map.put(atom, len);
}
// calc
StringBuilder sb = new StringBuilder();
map.forEach((k, v) -> {
sb.append(k);
if (v > 1) {
sb.append(v);
}
});
return sb.toString();
}
if (formula.contains("(")) {
int end = formula.indexOf(")");
int begin = formula.lastIndexOf("(", end);
int temp = 0;
int cur = end + 1;
while (cur < formula.length() && Character.isDigit(formula.charAt(cur))) {
temp = temp * 10 + Character.getNumericValue(formula.charAt(cur));
cur++;
}
if (temp == 0) {
temp = 1;
}
String ff = flat(formula.substring(begin + 1, end), temp);
formula = formula.substring(0, begin) + ff + formula.substring(cur);
}
return countOfAtoms(formula);
}
private String flat(String formula, int repeat) {
char[] cs = formula.toCharArray();
int temp = 0;
StringBuilder sb = new StringBuilder();
sb.append(cs[0]);
for (int i = 1; i < cs.length; i++) {
if (Character.isUpperCase(cs[i])) {
if (temp == 0) {
sb.append(repeat);
} else {
sb.append(temp * repeat);
}
temp = 0;
}
if (Character.isLetter(cs[i])) {
sb.append(cs[i]);
continue;
}
temp = temp * 10 + Character.getNumericValue(cs[i]);
}
if (temp == 0) {
sb.append(repeat);
} else {
sb.append(repeat * temp);
}
return sb.toString();
}