Skip to content

Commit 078605a

Browse files
committed
394.字符串解码,栈
1 parent 4739b0d commit 078605a

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

leetcode_Java/DoneTitle.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
322. 零钱兑换
101101
338. 比特位计数
102102
392. 判断子序列
103+
394. 字符串解码
103104
402. 移掉 K 位数字
104105
406. 根据身高重建队列
105106
415. 字符串相加

leetcode_Java/DoneType.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
20. 有效的括号(字符替换,哈希表)
173173
76. 最小覆盖子串(双指针,滑动窗口)
174174
151. 颠倒字符串中的单词(分割反转,双指针,双端队列)
175+
394. 字符串解码(栈)
175176
415. 字符串相加(模拟相加)
176177

177178

leetcode_Java/Solution0394.java

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// 394. 字符串解码
2+
3+
4+
/*
5+
栈:(这种解法更容易理解)
6+
1、把所有字符入栈,除了']'
7+
2、从栈取出[]内的字符串
8+
3、弹出'[',丢弃
9+
4、从栈获取倍数数字
10+
5、根据倍数把字母入栈
11+
6、把栈里面所有的字母取出来,得到结果
12+
*/
13+
class Solution {
14+
public String decodeString(String s) {
15+
Stack<Character> stack = new Stack<>();
16+
for (char c : s.toCharArray()) {
17+
if (c != ']') {
18+
stack.push(c);
19+
} else {
20+
StringBuilder sb = new StringBuilder();
21+
while (!stack.isEmpty() && Character.isLetter(stack.peek())) {
22+
sb.insert(0, stack.pop());
23+
}
24+
String sub = sb.toString();
25+
stack.pop();
26+
sb = new StringBuilder();
27+
while (!stack.isEmpty() && Character.isDigit(stack.peek())) {
28+
sb.insert(0, stack.pop());
29+
}
30+
int count = Integer.valueOf(sb.toString());
31+
while (count > 0) {
32+
for (char ch : sub.toCharArray()) {
33+
stack.push(ch);
34+
}
35+
count--;
36+
}
37+
}
38+
}
39+
StringBuilder res = new StringBuilder();
40+
while (!stack.isEmpty()) {
41+
res.insert(0, stack.pop());
42+
}
43+
return res.toString();
44+
}
45+
}
46+
47+
48+
/*
49+
栈:
50+
1、外层的解码需要等待内层解码的结果。先扫描的字符还用不上,但不能忘了它们。我们准备由内到外,层层解决[],需要保持对字符的记忆,于是用栈。
51+
2、变量含义:
52+
kStack:存放每一层[]的倍数,遇到'['时入栈暂存,遇到']'时出栈计算当前层解码结果
53+
resStack:存放上一层[]的子串,遇到'['时入栈暂存,遇到']'时出栈与当前层解码结果拼接
54+
res:表示当前层[]的子串,最外层没有[]
55+
k:表示当前层[]的倍数
56+
temp:表示当前层[]的解码结果
57+
2、入栈时机:遇到'[',意味着要开始解决内层的字符了,外层的数字和子串入栈暂存,并且变量归零用于内层继续计算
58+
1)当遇到'[',已经扫描的数字就是遇到的[]的“倍数”,入栈暂存
59+
2)当遇到'[',已经扫描的子串也入栈暂存,括号里的字符解码完后,再一起参与构建字符串
60+
3、出栈时机:遇到']',内层的字符串扫描完了,数字出栈构建新子串,旧子串出栈与新子串拼接得到最新结果
61+
62+
========== 过程一 =========
63+
s = "abc3[a2[d]]ef"
64+
65+
k = 3
66+
res = "abc"
67+
stack = [(3, "abc")]
68+
========== 过程二 =========
69+
s = "abc3[a2[d]]ef"
70+
71+
k = 2
72+
res = "a"
73+
stack = [(3, "abc"), (2, "a")]
74+
========== 过程三 =========
75+
s = "abc3[a2[d]]ef"
76+
77+
k = 0
78+
res = "d"
79+
curk = 2
80+
oldres = "a"
81+
stack = [(3, "abc")]
82+
temp = curk * res = "dd"
83+
res = oldres + curk * res = "add"
84+
========== 过程四 =========
85+
s = "abc3[a2[d]]ef"
86+
87+
k = 0
88+
res = "add"
89+
curk = 3
90+
oldres = "abc"
91+
stack = [(3, "abc")]
92+
temp = curk * res = "addaddadd"
93+
res = oldres + curk * res = "abcaddaddadd"
94+
========== 过程五 =========
95+
s = "abc3[a2[d]]ef"
96+
97+
res = "abcaddaddaddef"
98+
*/
99+
class Solution {
100+
public String decodeString(String s) {
101+
Deque<Integer> kStack = new ArrayDeque<>();
102+
Deque<StringBuilder> resStack = new ArrayDeque<>();
103+
StringBuilder res = new StringBuilder();
104+
int k = 0;
105+
for (char c : s.toCharArray()) {
106+
if (c >= '0' && c <= '9') {
107+
k = k * 10 + (c - '0');
108+
} else if (c == '[') {
109+
kStack.push(k);
110+
resStack.push(res);
111+
k = 0;
112+
res = new StringBuilder();
113+
} else if (c == ']') {
114+
StringBuilder temp = new StringBuilder();
115+
int kCur = kStack.pop();
116+
for (int i = 0; i < kCur; i++) {
117+
temp.append(res);
118+
}
119+
res = resStack.pop().append(temp);
120+
} else {
121+
res.append(c);
122+
}
123+
}
124+
return res.toString();
125+
}
126+
}

0 commit comments

Comments
 (0)