题目:
如果以化学专业名字解释,一句话概括:
输入结构简式,输出分子式(元素顺序按字母顺序)
例子:
输入 | 输出 |
H2O | H2O |
Mg(OH)2 | H2MgO2 |
K4(ON(SO3)2)2 | K4N2O14S4 |
Be32 | Be32 |
题解:
统计各元素总数。遇到括号,要把括号内的数量乘以括号右边的系数,括号可以嵌套。
用到两种数据结构:
散列表:用于存放元素名及其数量
栈:遇到左括号时,当前散列表入栈,用一个新的空表处理当前括号内的内容
(可以用递归调用代替栈)
编码实现思路:
不含括号的情况下,每解出一个元素及其数量,计算累积和可以抽象成:
累积和 += 当前元素 * 该元素数量
含括号的情况下,右括号出栈,出栈后可以抽象成:
累积和 += 括号内统计和 * 括号外数量
——两种情况下表达式一样,可以构建一个专门的处理函数,见源码__addtoDict()
Python源码:
import collections
class Solution(object):
def __addAtomtoDict(self, d, atom, count):
if d.__contains__(atom):
d[atom] = d[atom] + count
else:
d[atom] = count
def __addDicttoDict(self, d, d2, multiple):
for atom in d2.keys():
self.__addAtomtoDict(d, atom, d2[atom] * multiple)
def __addtoDict(self, d, elem, cnt):
if cnt == 0:
cnt = 1
if isinstance(elem, dict):
self.__addDicttoDict(d, elem, cnt)
elif isinstance(elem, str):
self.__addAtomtoDict(d, elem, cnt)
else:
pass
def countOfAtoms(self, formula):
i = 0
stack = collections.deque()
currDict = {}
currElem = None
currCnt = 0
for c in formula:
if c >= '0' and c <= '9':
currCnt = currCnt * 10 + ord(c) - ord('0')
elif c >= 'a' and c <= 'z':
currElem += c
# 遇到新元素,或左右括号,都把curr的元素统计入散列表Dict
elif c >= 'A' and c <= 'Z':
self.__addtoDict(currDict, currElem, currCnt)
currElem = c
currCnt = 0
elif c == '(':
self.__addtoDict(currDict, currElem, currCnt)
# 遇到左括号,把当前散列表入队,再开一个空散列表
stack.append(currDict)
currDict = {}
currElem = None
currCnt = 0
else: # ')'
self.__addtoDict(currDict, currElem, currCnt)
# 遇到右括号,弹栈
currElem = currDict
currCnt = 0
currDict = stack.pop()
# 最后,把缓冲区的加入字典
self.__addtoDict(currDict, currElem, currCnt)
ans = ""
atoms = list(currDict.keys())
atoms.sort()
for a in atoms:
ans += a
if currDict[a] > 1:
ans += str(currDict[a])
return ans
if __name__ == "__main__":
print(Solution().countOfAtoms("H2O"))
print(Solution().countOfAtoms("Mg(OH)2"))
print(Solution().countOfAtoms("K4(ON(SO3)2)2"))
print(Solution().countOfAtoms("Be32"))
执行用时:40 ms, 在所有 Python3 提交中击败了75.00%的用户
内存消耗:15.1 MB, 在所有 Python3 提交中击败了26.74%的用户