diff --git a/README.md b/README.md
index 96258db..3fc55ab 100644
--- a/README.md
+++ b/README.md
@@ -369,6 +369,11 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
- LeetCode 155. 最小栈
- LintCode 12. 带最小值操作的栈
+- [字符串解码](src/stack/decode-string.js)
+
+ - LeetCode 394. 字符串解码
+ - LintCode 575. 字符串解码
+
## 数学
- [阶乘后的零](src/math/factorial-trailing-zeroes.js)
diff --git a/src/stack/decode-string.js b/src/stack/decode-string.js
new file mode 100644
index 0000000..da36b31
--- /dev/null
+++ b/src/stack/decode-string.js
@@ -0,0 +1,36 @@
+// s = "3[a]2[bc]", 返回 "aaabcbc".
+// s = "3[a2[c]]", 返回 "accaccacc".
+// s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".
+/**
+ * @param {string} s
+ * @return {string}
+ */
+export const decodeString = function (s) {
+ const stack = []
+ let multiple = ''
+ for (let i = 0, len = s.length; i < len; i++) {
+ if (!isNaN(Number(s[i]))) { // 判断是数字
+ if (i === 0 || !isNaN(Number(s[i - 1]))) { // 如果上一位也是数字,则
+ multiple += s[i]
+ } else {
+ multiple = s[i]
+ }
+ } else if (multiple && s[i] === '[') {
+ stack.push(Number(multiple))
+ multiple = ''
+ } else if (s[i] === ']') {
+ let current = stack.pop()
+ let tmpStr = ''
+ while (typeof current !== 'number') {
+ tmpStr = current + tmpStr
+ current = stack.pop()
+ }
+ tmpStr = tmpStr.repeat(current)
+ stack.push(tmpStr)
+ } else {
+ stack.push(s[i])
+ }
+ }
+
+ return stack.join('')
+}
diff --git a/test/stack/decode-string.test.js b/test/stack/decode-string.test.js
new file mode 100644
index 0000000..28a36eb
--- /dev/null
+++ b/test/stack/decode-string.test.js
@@ -0,0 +1,7 @@
+import { decodeString } from '../../src/stack/decode-string'
+
+test('字符串解码', () => {
+ expect(decodeString('3[a]2[bc]')).toBe('aaabcbc')
+ expect(decodeString('3[a2[c]]')).toBe('accaccacc')
+ expect(decodeString('2[abc]3[cd]ef')).toBe('abcabccdcdcdef')
+})