力扣394——字元串解碼
- 2020 年 2 月 19 日
- 筆記
這道題主要涉及的是對遞歸和棧的理解。
原題
給定一個經過編碼的字元串,返回它解碼後的字元串。
編碼規則為: k[encoded_string],表示其中方括弧內部的 encoded_string 正好重複 k 次。注意 k 保證為正整數。
你可以認為輸入字元串總是有效的;輸入字元串中沒有額外的空格,且輸入的方括弧總是符合格式要求的。
此外,你可以認為原始數據不包含數字,所有的數字只表示重複的次數 k ,例如不會出現像 3a 或 2[4] 的輸入。
示例:
s = "3[a]2[bc]", 返回 "aaabcbc". s = "3[a2[c]]", 返回 "accaccacc". s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".
原題url:https://leetcode-cn.com/problems/decode-string/
解題
遞歸
這道題目,簡單來看就是根據數字和內容,進行不斷重複輸出,最終得出結果。因此,遞歸也是最容易讓人想到的。
數字代表內容需要重複的次數,[
代表一次新的遞歸開始,]
代表本次遞歸的結束,有點類似括弧匹配這種問題。只是需要記錄中間結果,以及最開始的s
進過一次遞歸遍歷後的下標位置。
基於上面的講解,我們也就能夠寫出程式碼:
class Solution { public String decodeString(String s) { StringBuilder resultSb = new StringBuilder(); dfs(s, 0, resultSb); return resultSb.toString(); } public int dfs(String s, int index, StringBuilder resultSb) { // 需要重複的次數 int count = 0; while (index < s.length()) { char temp = s.charAt(index); // 如果是數字,則先累計進count中 if (temp >= '0' && temp <= '9') { count = count * 10 + temp - '0'; } // 遇到'[',則開始新一輪的遞歸 else if (temp == '[') { StringBuilder tempResult = new StringBuilder(); index = dfs(s, index + 1, tempResult); // 重複 for (int i = 0; i < count; i++) { resultSb.append(tempResult); } // count進行重置 count = 0; } // 遇到']',結束遞歸 else if (temp == ']') { // 返回新的下標 return index; } // 遇到字母 else { resultSb.append(temp); } index++; } return index; } }
提交OK。
利用棧
既然有遞歸的寫法,那麼自然有不遞歸的寫法,這就需要藉助棧了。大家可以類比成計算一段普通的數學表達式,裡面有括弧、數字、符號運算等,所以需要兩個棧,分別存儲數字和運算符。
這道題目自然也是需要兩個棧的,一個用來存儲重複的次數,一個用來存儲中間的字元串結果。判斷出棧、入棧的依據,依據是[]
,[
代表數字和字元串都壓入相應的棧,]
代表需要將數字和字元串都需要從棧首壓出,進行計算。
接下來看看程式碼:
class Solution { public String decodeString(String s) { // 存放次數的棧 Stack<Integer> countStack = new Stack<>(); // 存放字元串的棧 Stack<StringBuilder> sbStack = new Stack<>(); // 臨時存儲字元串的內容 StringBuilder tempSb = new StringBuilder(); // 臨時存儲數字的內容 int tempCount = 0; // 遍歷 for(char temp : s.toCharArray()) { // 如果是數字,則先累計進tempCount中 if (temp >= '0' && temp <= '9') { tempCount = tempCount * 10 + temp - '0'; } // 遇到'[',將之前的數字和字元串放進countStack中 else if (temp == '[') { countStack.push(tempCount); tempCount = 0; sbStack.push(tempSb); tempSb = new StringBuilder(); } // 遇到']',從countStack拿出數字 else if (temp == ']') { // 重複 StringBuilder tempResult = new StringBuilder(); int count = countStack.pop(); for (int j = 0; j < count; j++) { tempResult.append(tempSb); } // 拿出sbStack第一個 StringBuilder sb = sbStack.pop(); tempSb = sb.append(tempResult); } // 遇到字母 else { tempSb.append(temp); } } return tempSb.toString(); } }
提交OK。
總結
以上就是這道題目我的解答過程了,不知道大家是否理解了。這道題主要涉及的是對遞歸和棧的理解,有點類似數學表達式的計算,只是做一下類比即可。