-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy path_726.java
110 lines (106 loc) · 4.76 KB
/
_726.java
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 com.fishercoder.solutions.firstthousand;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class _726 {
public static class Solution1 {
/*
* My completely original solution:
* 1. use a stack;
* 2. whenever we encounter the open paren, we push it into the top of the stack;
* 3. whenever we encounter an uppercase, we check to get its full atom letters,
* then check to get the number after it if there's any, then form a pair objet and push onto the stack;
* 4. whenever we encounter the closed paren, we check if there's any number after it,
* then poll all items on top of the stack off onto a new/temp stack until we encounter the corresponding open paren,
* then add these items from the temp stack back into the original/main stack;
*/
public String countOfAtoms(String formula) {
Deque<Pair> stack = new LinkedList<>();
for (int i = 0; i < formula.length(); i++) {
char curr = formula.charAt(i);
if (curr == '(') {
stack.addLast(new Pair("(", 1));
} else if (Character.isUpperCase(curr)) {
StringBuilder sb = new StringBuilder(curr + "");
i++;
while (i < formula.length() && Character.isLowerCase(formula.charAt(i))) {
sb.append(formula.charAt(i++));
}
if (i < formula.length()) {
if (Character.isUpperCase(formula.charAt(i))
|| formula.charAt(i) == '('
|| formula.charAt(i) == ')') {
// no numbers
stack.addLast(new Pair(sb.toString(), 1));
i--;
} else {
// there are numbers
StringBuilder numberSb = new StringBuilder();
while (i < formula.length() && Character.isDigit(formula.charAt(i))) {
numberSb.append(formula.charAt(i++));
}
i--;
stack.addLast(
new Pair(sb.toString(), Integer.parseInt(numberSb.toString())));
}
} else {
stack.addLast(new Pair(sb.toString(), 1));
}
} else if (curr == ')') {
i++;
StringBuilder sb = new StringBuilder();
while (i < formula.length() && Character.isDigit(formula.charAt(i))) {
sb.append(formula.charAt(i));
i++;
}
i--;
int number = 1;
if (sb.length() > 0) {
number = Integer.parseInt(sb.toString());
}
Deque<Pair> stack2 = new LinkedList<>();
while (!stack.isEmpty() && !stack.peekLast().atom.equals("(")) {
Pair pair = stack.pollLast();
stack2.addLast(new Pair(pair.atom, pair.count * number));
}
stack.pollLast(); // poll "(" off of the stack
while (!stack2.isEmpty()) {
stack.addLast(stack2.pollLast());
}
}
}
List<Pair> list = new ArrayList<>();
while (!stack.isEmpty()) {
list.add(stack.pollLast());
}
// now merge the same atoms
Map<String, Integer> map = new HashMap<>();
for (Pair pair : list) {
map.put(pair.atom, map.getOrDefault(pair.atom, 0) + pair.count);
}
// now add the merged atoms into the list again before sorting them
list.clear();
for (Map.Entry<String, Integer> entry : map.entrySet()) {
list.add(new Pair(entry.getKey(), entry.getValue()));
}
Collections.sort(list, (a, b) -> a.atom.compareToIgnoreCase(b.atom));
StringBuilder sb = new StringBuilder();
for (Pair pair : list) {
sb.append(pair.atom + (pair.count == 1 ? "" : pair.count));
}
return sb.toString();
}
class Pair {
String atom;
int count;
public Pair(String atom, int count) {
this.atom = atom;
this.count = count;
}
}
}
}