forked from wufenggirl/LeetCode-in-Golang
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathnumber-of-atoms.go
executable file
·110 lines (97 loc) · 1.77 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
package problem0726
import (
"sort"
"strconv"
)
func countOfAtoms(formula string) string {
return parse(count(formula))
}
func count(formula string) map[string]int {
rec := make(map[string]int, len(formula)/2)
var update = func(newRec map[string]int, times int) {
for atom, c := range newRec {
rec[atom] += c * times
}
}
atoms := ""
for len(formula) > 0 {
atoms, formula = cut(formula)
if atoms[0] == '(' {
newFormula, times := dealParenthese(atoms)
newRec := count(newFormula)
update(newRec, times)
} else {
atom, num := getAtomAndNum(atoms)
rec[atom] += num
}
}
return rec
}
func cut(formula string) (string, string) {
i := 1
if formula[0] == '(' {
i = jump(formula)
}
for i < len(formula) &&
!isUpper(formula[i]) &&
formula[i] != '(' {
i++
}
return formula[:i], formula[i:]
}
func dealParenthese(s string) (string, int) {
num, i := getNum(s)
return s[1 : i-1], num
}
func getAtomAndNum(s string) (string, int) {
num, i := getNum(s)
return s[:i], num
}
// 对于 "Ab321" 返回, 321 和 '3' 的索引号 2
func getNum(s string) (num, i int) {
i = len(s)
for 0 <= i-1 && isNum(s[i-1]) {
i--
}
num = 1
if i == len(s) {
return
}
num, _ = strconv.Atoi(s[i:])
return
}
func isNum(b byte) bool {
return '0' <= b && b <= '9'
}
func isUpper(b byte) bool {
return 'A' <= b && b <= 'Z'
}
// jump 跳过了圆括号部分
func jump(s string) int {
p := 1
i := 1
for i < len(s) && p > 0 {
if s[i] == '(' {
p++
} else if s[i] == ')' {
p--
}
i++
}
return i
}
func parse(r map[string]int) string {
atoms := make([]string, 0, len(r))
for a := range r {
atoms = append(atoms, a)
}
sort.Strings(atoms)
res := ""
for _, a := range atoms {
res += a
if r[a] > 1 {
res += strconv.Itoa(r[a])
}
}
return res
}