题目链接:
题目难度:困难
题目描述:
给定一个化学式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
只包含字母、数字和圆括号,并且题目中给定的是合法的化学式。
解题思路与解题代码:
# -*- coding: UTF-8 -*-
class Solution(object):
def countOfAtoms(self, formula):
stack = list()
# 第一步将每个元素、数字、括号独立出来,也就是说有的元素有两个字母组成,有的数字是10以上的
# 因此要把他们组合
i = 0
n = len(formula)
while i < n:
if formula[i].isalpha():
if formula[i].islower():
c = stack.pop()
c = c + formula[i]
stack.append(c)
else:
stack.append(formula[i])
i += 1
elif formula[i] == '(':
stack.append(formula[i])
i += 1
elif formula[i] == ')':
stack.append(formula[i])
i += 1
else:
num_str = formula[i]
i += 1
while i < n and formula[i].isdigit():
num_str += formula[i]
i += 1
stack.append(num_str)
# 组合结果如下
# print stack
# ['K', '4', '(', 'O', 'N', '(', 'S', 'O', '3', ')', '2', ')', '2']
# 第二步 有的元素只有一个,因此要把1补齐
i = 0
m = len(stack)-1
tmp_stack = list()
for i in range(m):
tmp_stack.append(stack[i])
if stack[i].isalpha():
if not stack[i+1].isdigit():
tmp_stack.append("1")
tmp_stack.append(stack[m])
if stack[m].isalpha():
tmp_stack.append("1")
stack = tmp_stack
# 补齐结果如下
# print stack
# ['K', '4', '(', 'O', '1', 'N', '1', '(', 'S', '1', 'O', '3', ')', '2', ')', '2']
# 第三步,开始遍历,进行计算,每次遇到一个“)”都往回找“(”,把括号外的数字乘进去,并组合元素和数字
stack2 = list()
i = 0
l = len(stack)
while i < l:
if stack[i].isalpha():
stack2.append([stack[i],stack[i+1]])
i += 2
elif stack[i] == '(':
stack2.append(stack[i])
i += 1
elif stack[i] == ')':
num = int(stack[i+1])
tmp = list()
c = stack2.pop()
while i > 0 and c != '(':
c1 = [c[0], str(int(c[1]) * num)]
tmp.append(c1)
c = stack2.pop()
stack2.extend(tmp)
i += 2
# print stack2
# [['K', '4'], ['S', '4'], ['O', '12'], ['N', '2'], ['O', '2']]
# 第四步,计算基本完成,将结果中重复元素合并,
result_dict = {}
for i in stack2:
if result_dict.has_key(i[0]):
count = result_dict[i[0]] + int(i[1])
result_dict[i[0]] = count
else:
result_dict[i[0]] = int(i[1])
result = ""
sor = sorted(result_dict)
for key in sor:
if result_dict[key] == 1:
result += key
else:
result += str(key)+str(result_dict[key])
print result
# K4N2O14S4
return result
# a = Solution()
# a.countOfAtoms("K4(ON(SO3)2)2")
时间复杂度: O(n)