package hashing; import java.util.*; /** * Created by gouthamvidyapradhan on 06/08/2019 Given a chemical formula (given as a string), return * the count of each atom. * *

An atomic element always starts with an uppercase character, then zero or more lowercase * letters, representing the name. * *

1 or more digits representing the count of that element may follow if the count is greater * than 1. If the count is 1, no digits will follow. For example, H2O and H2O2 are possible, but * H1O2 is impossible. * *

Two formulas concatenated together produce another formula. For example, H2O2He3Mg4 is also a * formula. * *

A formula placed in parentheses, and a count (optionally added) is also a formula. For * example, (H2O2) and (H2O2)3 are formulas. * *

Given a formula, output 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. * *

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}. Note: * *

All atom names consist of lowercase letters, except for the first character which is * uppercase. The length of formula will be in the range [1, 1000]. formula will only consist of * letters, digits, and round parentheses, and is a valid formula as defined in the problem. * *

Solution O(N ^ 2) Recursively solve each substring within round braces as subformula. Consider * each subformula as right subformula and each each subformula before the round braces as left * subformula - sum up value of both left and right subformula to get the answer. */ public class NumberOfAtoms { public static void main(String[] args) { String result = new NumberOfAtoms().countOfAtoms("K4(((K4)K4)2)2"); System.out.println(result); } public String countOfAtoms(String formula) { Map atomCountResult = new NumberOfAtoms().countOfAtoms(formula, 0); List sortedKeys = new ArrayList<>(atomCountResult.keySet()); sortedKeys.sort(Comparator.naturalOrder()); StringBuilder result = new StringBuilder(); for (String k : sortedKeys) { int count = atomCountResult.get(k); if (count > 1) { result.append(k).append(count); } else result.append(k); } return result.toString(); } private Map countOfAtoms(String formula, int startPos) { Map left = new HashMap<>(); StringBuilder atom = new StringBuilder(); StringBuilder atomCount = new StringBuilder(); for (int i = startPos; i < formula.length(); ) { char c = formula.charAt(i); if (c >= 'A' && c <= 'Z') { if (atom.length() > 0) { int count = 1; if (atomCount.length() > 0) { count = Integer.parseInt(atomCount.toString()); } String atomKey = atom.toString(); if (left.containsKey(atomKey)) { left.put(atomKey, left.get(atomKey) + count); } else left.put(atom.toString(), count); atom = new StringBuilder(); atomCount = new StringBuilder(); } atom.append(c); i++; } else if (c >= 'a' && c <= 'z') { atom.append(c); i++; } else if (c >= '0' && c <= '9') { atomCount.append(c); i++; } else { // this is equal to '(' if (atom.length() > 0) { int count = 1; if (atomCount.length() > 0) { count = Integer.parseInt(atomCount.toString()); } String atomKey = atom.toString(); if (left.containsKey(atomKey)) { left.put(atomKey, left.get(atomKey) + count); } else left.put(atom.toString(), count); atom = new StringBuilder(); atomCount = new StringBuilder(); } int j = i, count = 0; for (int l = formula.length(); j < l; j++) { if (formula.charAt(j) == '(') { count++; } else if (formula.charAt(j) == ')') { count--; } if (count == 0) break; } Map right = countOfAtoms(formula.substring(i + 1, j), 0); j++; StringBuilder rightAtomCount = new StringBuilder(); for (int l = formula.length(); j < l; j++) { if (formula.charAt(j) >= '0' && formula.charAt(j) <= '9') { rightAtomCount.append(formula.charAt(j)); } else break; } if (rightAtomCount.length() > 0) { int mulFactor = Integer.parseInt(rightAtomCount.toString()); for (String k : right.keySet()) { right.put(k, right.get(k) * mulFactor); } } left = merge(left, right); i = j; } } if (atom.length() > 0) { int count = 1; if (atomCount.length() > 0) { count = Integer.parseInt(atomCount.toString()); } String atomKey = atom.toString(); if (left.containsKey(atomKey)) { left.put(atomKey, left.get(atomKey) + count); } else left.put(atom.toString(), count); } return left; } private Map merge(Map left, Map right) { for (String k : left.keySet()) { if (right.containsKey(k)) { right.put(k, right.get(k) + left.get(k)); } else right.put(k, left.get(k)); } return right; } }