-
Notifications
You must be signed in to change notification settings - Fork 8
/
DecodeString.java
143 lines (125 loc) · 4.18 KB
/
DecodeString.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
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
package stack;
// Source : https://leetcode.com/problems/decode-string/
// Id : 394
// Author : Fanlu Hai | https://github.com/Fanlu91/FanluLeetcode
// Date : 2019-06-13
// Topic : Stack,String
// Level : Medium
// Other : stack or recursive
// Tips :
// Result : 100.00% 100.00%
import java.util.*;
public class DecodeString {
// 5.62% 32 ms 84.38%
public String decodeStringOrigin(String s) {
Stack<Character> stack = new Stack<>();
List<Character> tmpList = new LinkedList<>();
char[] chars = s.toCharArray();
char tmpChar;
String num = "";
for (int i = 0; i < chars.length; i++) {
if (chars[i] == ']') {
// address each ] by decoding and to back to stack before moving forward.
tmpChar = stack.pop();
while (tmpChar != '[') {
tmpList.add(0, tmpChar);
tmpChar = stack.pop();
}
// reach [ , try to get the multiply operand
while (!stack.isEmpty() && Character.isDigit(stack.peek())) {
num = stack.pop() + num;
}
// do the multiply
for (int j = 0; j < Integer.valueOf(num); j++) {
stack.addAll(tmpList);
}
tmpList.clear();
num = "";
} else {
stack.push(chars[i]);
}
}
StringBuilder ans = new StringBuilder();
stack.forEach(k -> {
ans.append(k);
});
return ans.toString();
}
/**
* learned from leetcode submissions.
* <p>
* Main problem of my solution is it still store tmp value as character, a lot characters will be revisited
* that is not very efficient.
*/
// 100.00% 0ms 100.00%
public String decodeString(String s) {
String res = "";
Stack<Integer> countStack = new Stack();
Stack<String> resStack = new Stack();
int index = 0;
while (index < s.length()) {
if (Character.isDigit(s.charAt(index))) {
int count = 0;
while (Character.isDigit(s.charAt(index))) {
count = 10 * count + (s.charAt(index) - '0');
index++;
}
countStack.push(count);
} else if (s.charAt(index) == '[') {
// push current res to stack, create a new res to store whatever is behind [
resStack.push(res);
res = "";
index++;
} else if (s.charAt(index) == ']') {
// decode res when ] is reached
StringBuilder temp = new StringBuilder(resStack.pop());
int repeatTimes = countStack.pop();
for (int i = 0; i < repeatTimes; i++) {
temp.append(res);
}
res = temp.toString();
index++;
} else {
res = res + s.charAt(index++);
}
}
return res;
}
/**
* Learned from leetcode discussion.
* Recursive. helper(s) consumes one layer of "[ ]".
*/
int idx;
// 100% 100%
public String decodeStringRecursive(String s) {
idx = 0;
return helper(s);
}
String helper(String s) {
StringBuilder ans = new StringBuilder();
//
for (; idx < s.length(); idx++) {
int k = 0;
char ch = s.charAt(idx);
if (ch == '[') {
idx++;
String str = helper(s);
while (k > 0) {
ans.append(str);
--k;
}
} else if (ch == ']') {
// break out the for loop for return
break;
} else if (Character.isDigit(ch)) {
k = k * 10 + ch - '0';
} else
ans.append(ch);
}
return ans.toString();
}
public static void main(String[] args) {
DecodeString decodeString = new DecodeString();
System.out.println(decodeString.decodeStringRecursive("2[ab]c3[de]"));
}
}