Java and Python code - recursive and possibly easier to understand with comments
Python code:\n\n\nclass Solution:\n    def __init__(self):\n        self.i = 0\n    \n    def countOfAtoms(self, formula):\n        ans = \'\'\n        counts =
Python code:\n\n```\nclass Solution:\n    def __init__(self):\n        self.i = 0\n    \n    def countOfAtoms(self, formula):\n        ans = \'\'\n        counts = self.countRecursive(formula) # recursive function\n        for name in sorted(counts.keys()): # collect the result and output\n            freq = counts[name]\n            ans += name\n            if freq> 1:\n                ans += (str(freq))\n        return ans\n    \n    def countRecursive(self, f):\n        ans = dict()\n        while self.i != len(f):\n            if f[self.i] == \'(\':\n                self.i += 1\n                tmp = self.countRecursive(f) # recursively call to sove \n\t\t\t\t#the (I am inside the backet to be solved recursively)\n                count = self.getCount(f)\n                for akey, afreq in tmp.items():\n                    ans[akey] = ans.get(akey, 0) + afreq*count \n\t\t\t\t\t# alike (OH)2, inside (), OH\'s freq are all 1 and then 1*2 outside ()\n            elif f[self.i] == \')\':\n                self.i += 1\n                return ans \n\t\t\t\t# since we face ), then we return this exactly corresponds to " if f[self.i] == \'(\':"\n            else:\n                aname = self.getName(f) # take the name, e.g., Mg\n                acount = self.getCount(f) # take the count\n                ans[aname] = ans.get(aname, 0) + acount\n        return ans\n    \n    def getName(self, f):\n        name = f[self.i]\n        self.i += 1\n        while self.i < len(f) and ord(\'a\') <= ord(f[self.i]) <= ord(\'z\'):\n            name += f[self.i]\n            self.i += 1\n        return name\n    \n    def getCount(self, f):\n        count = 0\n        while self.i < len(f) and ord(\'0\') <= ord(f[self.i]) <= ord(\'9\'):\n            count = count * 10 + int(f[self.i])\n            self.i += 1\n        return 1 if count == 0 else count\n    \n```\n\nJava code with exactly the same idea with Python code:\n```\n    class Solution {\n    private int i;\n    public String countOfAtoms(String formula) {\n        StringBuilder ans = new StringBuilder();\n        i = 0; //global\n        Map<String, Integer> counts = countRecursive(formula.toCharArray()); \n\t\t//\u6536\u96C6\u7ED3\u679C\u5E76\u663E\u793A\u6253\u5370\uFF0C\u8FD9\u4E2A\u903B\u8F91\u4E5FOk\uFF0C\u5982\u679C\u6570\u91CF\u4E3A1\uFF0C\u5219\u7701\u7565\n        for (String name: counts.keySet()){\n            ans.append(name);\n            int count = counts.get(name);\n            if (count > 1){\n                ans.append("" + count);\n            }\n        }\n        return ans.toString();\n    }\n    \n    private Map<String, Integer> countRecursive(char[] f){\n        Map<String, Integer> ans = new TreeMap<String, Integer>();  \n\t\t//\u9700\u8981\u6309\u7167\u540D\u5B57\u6392\u5E8F\n        while (i != f.length){\n            if (f[i] == \'(\'){ //\u9047\u5230\u5DE6\u62EC\u53F7\u7684\u65F6\u5019\uFF0C\u5F00\u59CB\u9012\u5F52\u6C42\u89E3\uFF08\uFF09\u5185\u90E8\u7684\u4E32\u7684\u89E3\u6790\u7ED3\u679C\uFF0C\u7136\u540E\u7ED3\u679C\u8FD4\u56DE\u7ED9tmp\uFF0C\n\t\t\t//tmp\u7684\u7ED3\u679C\u548C\u5F53\u524D\u7684\u7ED3\u679C\u5408\u5E76\n                i += 1;\n                Map<String, Integer> tmp = countRecursive(f); //\u9012\u5F52\u6C42\u89E3\u5B50\u95EE\u9898\uFF01\u4F1A\u81EA\u52A8\u627E\u5230)\u8FD9\u4E2Aposition\n                int count = getCount(f); //\u62EC\u53F7\u5916\u9762\u7684\u6B21\u6570\n                \n                for(Map.Entry<String, Integer> entry: tmp.entrySet()){\n                    ans.put(entry.getKey(), ans.getOrDefault(entry.getKey(), 0) + entry.getValue() * count);\n                }\n            }\n            else if(f[i] == \')\'){\n                i += 1;\n                return ans;\n            }\n            else{\n                String name = getName(f);\n                ans.put(name, ans.getOrDefault(name, 0) + getCount(f));\n            }\n        }\n        return ans;\n    }\n    \n    private String getName(char[] f){ //\u6839\u636E\u5168\u5C40\u53D8\u91CFi\uFF0C\u6765\u5BFB\u627E\u4EE5i\u4F4D\u7F6E\u6253\u5934\u7684\u4E00\u4E2A\u5143\u7D20\u7684\u540D\u5B57\uFF0C\u4F8B\u5982Mg\n        String name = "" + f[i];\n        i += 1;\n        while (i < f.length && \'a\' <= f[i] && f[i] <= \'z\'){\n            name += f[i];\n            i += 1;\n        }\n        return name;\n    }\n    \n    private int getCount(char[] f){ //\u6839\u636E\u5168\u5C40\u53D8\u91CFi\uFF0C\u6765\u5BFB\u627E\u4EE5i\u4F4D\u7F6E\u6253\u5934\u7684\u6570\u5B57\u7684\u4E32\uFF0C\u4F8B\u598212\n        int count = 0;\n        while (i < f.length && \'0\' <= f[i] && f[i] <=\'9\'){\n            count = count * 10 + (f[i] - \'0\');\n            i += 1;\n        }\n        return count == 0 ? 1: count;\n    }\n }\n```
[]