力扣394——字符串解碼

這道題主要涉及的是對遞歸和棧的理解。

原題

給定一個經過編碼的字符串,返回它解碼後的字符串。

編碼規則爲: 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。

總結

以上就是這道題目我的解答過程了,不知道大家是否理解了。這道題主要涉及的是對遞歸和棧的理解,有點類似數學表達式的計算,只是做一下類比即可。

有興趣的話可以訪問我的博客或者關注我的公衆號、頭條號,說不定會有意外的驚喜。

https://death00.github.io/

公衆號:健程之道

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章