[LeetCode] 394. Decode String(解码字符串)
-
Difficulty: Medium
-
Related Topics: Stack, Depth-first Search
Description
Given an encoded string, return its decoded string.
给一个编码过的字符串,返回解码后的字符串。
The encoding rule is: k[encoded_string]
, where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer.
编码规则是 k[encoded_string]
,其中方括号内部的 encoded_string 需要重复正好 k 次。输入保证 k 是一个正数。
You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc.
你可以假定输入总是合法的;没有多余的空格,方括号总是合法的等。
Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won't be input like 3a
or 2[4]
.
并且,你可以假定解码后的字符串不含任何数字,换句话说,编码字符串里的数字永远只表示重复的次数。例如,没有像 3a
或 2[4]
这样的输入。
Examples
Example 1
Input: s = "3[a]2[bc]"
Output: "aaabcbc"
Example 2
Input: s = "3[a2[c]]"
Output: "accaccacc"
Example 3
Input: s = "2[abc]3[cd]ef"
Output: "abcabccdcdcdef"
Example 4
Input: s = "abc3[cd]xyz"
Output: "abccdcdcdxyz"
Solution
一道手写解析器的题目,耐着性子按规则来就问题不大:
-
遇到数字:开始记录重复次数;
-
遇到左方括号
[
:进入递归处理,处理过程中消耗对应的右方括号]
; -
遇到其它情况:直接加入结果集。‘
我自己的代码如下(这个代码自认写得有点难看):
class Solution {
fun decodeString(s: String): String {
val result = StringBuilder()
var i = 0
var repeatedTime = 0
while (i < s.length) {
val ch = s[i]
when {
ch.isDigit() -> {
repeatedTime = 10 * repeatedTime + ch.numericValue()
i++
}
ch == '[' -> {
i = doRepeat(s, i + 1, repeatedTime, result)
repeatedTime = 0
}
else -> {
result.append(ch)
i++
}
}
}
return result.toString()
}
private fun doRepeat(s: String, startIndex: Int, repeatTime: Int, result: Appendable): Int {
var i = startIndex
val sb = StringBuilder()
var innerRepeatTime = 0
while (i < s.length && s[i] != ']') {
val ch = s[i]
when {
ch.isDigit() -> {
innerRepeatTime = 10 * innerRepeatTime + ch.numericValue()
i++
}
ch == '[' -> {
i = doRepeat(s, i + 1, innerRepeatTime, sb)
innerRepeatTime = 0
}
else -> {
sb.append(ch)
i++
}
}
}
result.append(sb.repeat(repeatTime))
return i + 1
}
private fun Char.numericValue(): Int {
return Character.getNumericValue(this)
}
}
我这个解法虽然能解题,但总感觉写得不够优雅,翻阅 discussion,找到了个和我类似的解法,但这个递归比我的优雅多了:
import java.util.*
class Solution {
fun decodeString(s: String): String {
val queue: Queue<Char> = ArrayDeque()
s.forEach { queue.offer(it) }
return helper(queue)
}
private fun helper(queue: Queue<Char>): String {
val result = StringBuilder()
var repeatTime = 0
loop@ while (queue.isNotEmpty()) {
val c = queue.poll()
when {
c.isDigit() -> repeatTime = 10 * repeatTime + c.numericValue()
c == '[' -> {
val repeatStr = helper(queue)
result.append(repeatStr.repeat(repeatTime))
repeatTime = 0
}
c == ']' -> {
break@loop
}
else -> {
result.append(c)
}
}
}
return result.toString()
}
private fun Char.numericValue(): Int {
return Character.getNumericValue(this)
}
}