Given a string formula representing a chemical formula, return the count of each atom.
The atomic element always starts with an uppercase character, then zero or more lowercase letters, representing the name.
One or more digits representing that element's count may follow if the count is greater than 1. If the count is 1, no digits will follow.
"H2O" and "H2O2" are possible, but "H1O2" is impossible.Two formulas are concatenated together to produce another formula.
"H2O2He3Mg4" is also a formula.A formula placed in parentheses, and a count (optionally added) is also a formula.
"(H2O2)" and "(H2O2)3" are formulas.Return the count of all elements as a string in the following form: the first name (in sorted order), followed by its count (if that count is more than 1), followed by the second name (in sorted order), followed by its count (if that count is more than 1), and so on.
The test cases are generated so that all the values in the output fit in a 32-bit integer.
Example 1:
Input: formula = "H2O"
Output: "H2O"
Explanation: The count of elements are {'H': 2, 'O': 1}.
Example 2:
Input: formula = "Mg(OH)2"
Output: "H2MgO2"
Explanation: The count of elements are {'H': 2, 'Mg': 1, 'O': 2}.
Example 3:
Input: formula = "K4(ON(SO3)2)2"
Output: "K4N2O14S4"
Explanation: The count of elements are {'K': 4, 'N': 2, 'O': 14, 'S': 4}.
Constraints:
1 <= formula.length <= 1000formula consists of English letters, digits, '(', and ')'.formula is always valid.class Solution {
private class Element {
public String atom;
public int valency;
public Element(String atom, int valency) {
this.atom = atom;
this.valency = valency;
}
public String toString() {
return "{" + atom + valency + "}";
}
}
public String countOfAtoms(String formula) {
Stack<Element> stk = new Stack<>();
formula = formula + "_"; // Mark end of formula
char[] F = formula.toCharArray();
String elem = "";
int num = 0;
for (char c : F) {
if (c >= '0' && c <= '9') {
stk.peek().valency = stk.peek().valency * 10 + c - '0';
continue;
} else if (c >= 'A' && c <= 'Z') {
elem = String.valueOf(c);
num = 0;
} else if (c >= 'a' && c <= 'z') {
stk.peek().atom += c;
continue;
} else if (c == '('){
elem = "(";
} else if (c == ')') {
elem = ")";
}
if (!stk.empty() && stk.peek().atom == ")"){
int multiplier = stk.pop().valency;
Stack<Element> interim = new Stack<>();
while (stk.peek().atom != "(") {
Element top = stk.pop();
if (top.valency == 0)
top.valency = 1;
top.valency *= multiplier;
interim.push(top);
}
stk.pop();
while (!interim.isEmpty())
stk.push(interim.pop());
}
stk.push(new Element(elem, num));
elem = "";
num = 0;
// System.out.println(stk.toString());
}
Map<String, Integer> freq = new TreeMap<>();
while(!stk.isEmpty()){
Element top = stk.pop();
if (top.valency == 0)
top.valency = 1;
freq.put(top.atom, freq.getOrDefault(top.atom, 0)+top.valency);
}
StringBuilder sb = new StringBuilder();
for(Map.Entry<String, Integer> e: freq.entrySet()){
sb.append(e.getKey());
if(e.getValue()!=1)
sb.append(e.getValue());
}
return sb.toString();
}
}