-
Notifications
You must be signed in to change notification settings - Fork 0
/
number-of-atoms.go
151 lines (128 loc) · 3.22 KB
/
number-of-atoms.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"sort"
"strconv"
)
// 726 https://leetcode-cn.com/problems/number-of-atoms/
// 这题可以参照 Dijkstra 的双栈算术表达式求值算法(《算法-第四版》 80 页),其实不难,但是很烦
func isNum(s byte) bool { return s >= '0' && s <= '9' }
func isLowerLatter(s byte) bool { return s >= 'a' && s <= 'z' }
func isUpperLatter(s byte) bool { return s >= 'A' && s <= 'Z' }
func countOfAtoms(formula string) string {
strStack := []string{}
numStack := []int{}
var pre byte
for i := 0; i < len(formula); i++ {
s := formula[i]
haveNext := i+1 < len(formula)
// 大写字母处理
if isUpperLatter(s) {
strStack = append(strStack, string(s))
if (haveNext && !isNum(formula[i+1]) && !isLowerLatter(formula[i+1])) || !haveNext {
numStack = append(numStack, 1)
}
pre = s
continue
}
// 小写字母处理
if isLowerLatter(s) {
strStack[len(strStack)-1] = strStack[len(strStack)-1] + string(s)
if (haveNext && !isNum(formula[i+1]) && !isLowerLatter(formula[i+1])) || !haveNext {
numStack = append(numStack, 1)
}
pre = s
continue
}
// 数字处理
if isNum(s) {
if isNum(pre) {
numStr := strconv.Itoa(numStack[len(numStack)-1])
numStr += string(s)
newNum, _ := strconv.Atoi(numStr)
numStack[len(numStack)-1] = newNum
} else {
num, _ := strconv.Atoi(string(s))
numStack = append(numStack, num)
}
pre = s
continue
}
// 右括号处理 取出 strStack 中的所有原子,直到遇到 "(" ,从 numStack 中取出相同数量元素分别和 ")" 后面数字相乘
// 再将新的 str 和 num 压回 strStack 和 numStack
if string(s) == ")" {
ss := []string{}
ns := []int{}
base := 1
// 取出右括号后所有的数字
if i+1 < len(formula) && isNum(formula[i+1]) {
j := 1
numStr := ""
for i+1 < len(formula) && isNum(formula[i+1]) {
if i+j <= len(formula)-1 && isNum(formula[i+j]) {
numStr += string(formula[i+j])
j++
} else {
break
}
}
base, _ = strconv.Atoi(numStr)
// 跳过 j-1 个字符
i = i + (j - 1)
}
for {
str := strStack[len(strStack)-1]
strStack = strStack[:len(strStack)-1]
// 直到取到 "("
if str == "(" {
break
}
ss = append(ss, str)
num := numStack[len(numStack)-1]
numStack = numStack[:len(numStack)-1]
ns = append(ns, num)
}
ln := len(ns)
for i := 0; i < ln; i++ {
// 压入新数字
num := ns[len(ns)-1]
ns = ns[:len(ns)-1]
newNum := num * base
numStack = append(numStack, newNum)
// 压入字符
str := ss[len(ss)-1]
ss = ss[:len(ss)-1]
strStack = append(strStack, str)
}
pre = s
continue
}
strStack = append(strStack, string(s))
pre = s
}
m := map[string]int{}
atoms := []string{}
for i := 0; i < len(strStack); i++ {
m[strStack[i]] = m[strStack[i]] + numStack[i]
atoms = add(atoms, strStack[i])
}
sort.Strings(atoms)
ans := ""
for _, atom := range atoms {
if m[atom] == 1 {
ans += atom
continue
}
ans += atom + strconv.Itoa(m[atom])
}
return ans
}
// 去重
func add(s []string, e string) []string {
for _, v := range s {
if v == e {
return s
}
}
s = append(s, e)
return s
}