給定一個經過編碼的字串,傳回它解碼後的字串。
編碼規則為: k[encoded_string],表示其中方括號內部的 encoded_string 正重複 k 次。注意 k 保證為正整數。
你可以認為輸入字串總是有效的;輸入字串中沒有額外的空格,且輸入的方括號總是符合格式要求的。
此外,你可以認為原始資料不包含數字,所有的數字只表示重複的次數 k ,例如不會出現像 3a 或 2[4] 的輸入。
範例1:
輸入:s = "3[a]2[bc]"
#輸出:"aaabcbc"
範例2:
輸入:s = "3[a2[c]] "
輸出:"accaccacc"
範例3:
#範例3:
範例4:輸入:s = "abc3[cd]xyz"#輸出:"abccdcdcdxyz"
方法一:堆疊(Java)
首先因為數字可能不只一位,為了更清晰方便可以使用兩個堆疊,一個儲存數字,一個儲存字元。當遇到除了]外的字元先入字元棧,遇到數字則將完整的數字轉換後入數字棧,而當遇到]時將字元棧中彈出直到[為止的字元構成一個臨時字串,並彈出數字棧頂元素,將臨時字串重複該數字次數後重新入字元棧。
具體方法思路:遍歷這個堆疊
如果當前的字元為數位,解析出一個數字(連續的多個數位)並進棧
#如果目前的字元為字母或左括號,直接進棧
class Solution { int ptr; public String decodeString(String s) { LinkedList<String> stk = new LinkedList<String>(); ptr = 0; while (ptr < s.length()) { char cur = s.charAt(ptr); if (Character.isDigit(cur)) { // 获取一个数字并进栈 String digits = getDigits(s); stk.addLast(digits); } else if (Character.isLetter(cur) || cur == '[') { // 获取一个字母并进栈 stk.addLast(String.valueOf(s.charAt(ptr++))); } else { ++ptr; LinkedList<String> sub = new LinkedList<String>(); while (!"[".equals(stk.peekLast())) { sub.addLast(stk.removeLast()); } Collections.reverse(sub); // 左括号出栈 stk.removeLast(); // 此时栈顶为当前 sub 对应的字符串应该出现的次数 int repTime = Integer.parseInt(stk.removeLast()); StringBuffer t = new StringBuffer(); String o = getString(sub); // 构造字符串 while (repTime-- > 0) { t.append(o); } // 将构造好的字符串入栈 stk.addLast(t.toString()); } } return getString(stk); } public String getDigits(String s) { StringBuffer ret = new StringBuffer(); while (Character.isDigit(s.charAt(ptr))) { ret.append(s.charAt(ptr++)); } return ret.toString(); } public String getString(LinkedList<String> v) { StringBuffer ret = new StringBuffer(); for (String s : v) { ret.append(s); } return ret.toString(); } }
時間複雜度:O(N)
方法二:遞迴(Go)
需要解決多個括號之間的巢狀問題。也就是重疊子問題。使用棧或遞歸的解題方式都是可以。
1、先標識右括號結束的位置。
2、遇到左括號,i 1傳遞給下一次
3、結束左括號的運行將乘積次數置零, i=上一次右括號接觸的位置。繼續將右括號外面剩餘的字元加完。
具體思維:從左向右解析字串:
#如果目前位置為數字位,那麼後面一定包含一個用方括號所表示的字串,即屬於這種情況:k[...]:
我們可以先解析出一個數字,然後解析到了左括號,遞歸向下解析後面的內容,遇到對應的右括號就返回,此時我們可以根據解析出的數字x 解析出的括號裡的字串s' 構造出一個新的字串X * s′
我們把k[...] 解析結束後,再呼叫遞歸函數,解析右括號右邊的內容
###如果目前位置是字母位,那麼我們直接解析目前這個字母,然後遞歸向下解析這個字母後面的內容。 #########func decodeString(s string) string { var decode func(start int) (string, int) decode = func(start int) (str string, end int) { num:= 0 for i := start; i < len(s); i++ { if isNumber(s[i]) { num = num*10 + int(s[i]-'0') } else if isLetter(s[i]) { str += string(s[i]) } else if s[i] == '[' { item, index := decode(i + 1) for num != 0 { str += item num-- } i = index } else if s[i] == ']' { end = i break } } return str, end } res, _ := decode(0) return res } func isLetter(u uint8) bool { return u >= 'A' && u <= 'Z' || u >= 'a' && u <= 'z' } func isNumber(u uint8) bool { return u >= '0' && u <= '9' }###時間複雜度:O(N)######空間複雜度:O(N)###
以上是如何使用Go Java演算法進行字串解碼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!