394. Decode String

Description

Given an encoded string, return it's 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.

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].

Examples:

s = "3[a]2[bc]", return "aaabcbc".
s = "3[a2[c]]", return "accaccacc".
s = "2[abc]3[cd]ef", return "abcabccdcdcdef".

Solution

DFS

這道題讓我們把一個按一定規則編碼后的字符串解碼成其原來的模樣,編碼的方法很簡單,就是把重復的字符串放在一個中括號里,把重復的次數放在中括號的前面,注意中括號里面有可能會嵌套中括號,這題可以用遞歸和迭代兩種方法來解。

我們首先來看遞歸的解法,我們把一個中括號中的所有內容看做一個整體,一次遞歸函數返回一對中括號中解碼后的字符串。給定的編碼字符串實際上只有四種字符,數字,字母,左中括號,和右中括號。那么我們開始用一個變量i從0開始遍歷到字符串的末尾,由于左中括號都是跟在數字后面,所以我們首先遇到的字符只能是數字或者字母,如果是字母,我們直接存入結果中,如果是數字,我們循環讀入所有的數字,并正確轉換,那么下一位非數字的字符一定是左中括號,我們指針右移跳過左中括號,對之后的內容調用遞歸函數求解,注意我們循環的停止條件是遍歷到末尾和遇到右中括號,由于遞歸調用的函數返回了子中括號里解碼后的字符串,而我們之前把次數也已經求出來了,那么循環添加到結果中即可,參見代碼如下:

注意遞歸需要返回當前層處理到哪個index之前,否則上層無法得知改從哪里開始繼續處理。換言之,上層需要知道下層處理到什么地方了,即’]'的位置。我這里返回的idx代表該從哪里開始,即']'的后一個位置。

class Solution {
    public String decodeString(String s) {
        return decode(s.toCharArray(), 0).str;
    }
    
    public Pair decode(char[] arr, int start) {
        StringBuilder sb = new StringBuilder();
        int i = start;
        
        while (i < arr.length) {
            if (Character.isDigit(arr[i])) {
                int count = 0;
                while (Character.isDigit(arr[i])) {
                    count = 10 * count + (arr[i++] - '0');
                }
                // arr[i] should be '[' now
                Pair sub = decode(arr, i + 1);
                while (count-- > 0) {
                    sb.append(sub.str);
                }
                i = sub.idx;
            } else if (arr[i] == ']') {     // consume one ']'
                ++i;
                break;
            } else {
                sb.append(arr[i++]);
            }
        }
        
        
        return new Pair(sb.toString(), i);
    }
    
    class Pair {
        String str;
        int idx;
        
        public Pair(String str, int idx) {
            this.str = str;
            this.idx = idx;
        }
    }
}

Stack, time O(n), space O(n)

用Stack做更賞心悅目一點。

class Solution {
    public String decodeString(String s) {
        if (s == null || s.isEmpty()) {
            return s;
        }
        
        Stack<Integer> countStack = new Stack<>();  // peek() is curr level count
        Stack<String> strStack = new Stack<>();     // peek() is prev level str
        int i = 0;
        String res = "";    // store curr level str
        
        while (i < s.length()) {
            char c = s.charAt(i);
            
            if (Character.isDigit(c)) {
                int count = 0;
                // count might be over 1-digit length
                while (i < s.length() && Character.isDigit(s.charAt(i))) {
                    count = 10 * count + s.charAt(i) - '0';
                    ++i;
                }
                
                countStack.push(count);
            } else if (c == '[') {  // enter a new level, push and clear res
                strStack.push(res);
                res = "";
                ++i;
            } else if (c == ']') {  // curr level ends, merge it into prev level
                StringBuilder sb = new StringBuilder();
                sb.append(strStack.pop());
                int count = countStack.pop();
                
                while (count-- > 0) {
                    sb.append(res);
                }
                
                res = sb.toString();
                ++i;
            } else {
                res += c;
                ++i;
            }
        }
        
        return res;
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容