1. 程式人生 > >394. Decode String (解碼字串)

394. Decode String (解碼字串)

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

這道題讓我們把一個按一定規則編碼後的字串解碼成其原來的模樣,編碼的方法很簡單,就是把重複的字串放在一箇中括號裡,把重複的次數放在中括號的前面,注意中括號裡面有可能會巢狀中括號,這題可以用遞迴和迭代兩種方法來解,我們首先來看遞迴的解法,我們把一箇中括號中的所有內容看做一個整體,一次遞迴函式返回一對中括號中解碼後的字串。給定的編碼字串實際上只有四種字元,數字,字母,左中括號,和右中括號。那麼我們開始用一個變數i從0開始遍歷到字串的末尾,由於左中括號都是跟在數字後面,所以我們首先遇到的字元只能是數字或者字母,如果是字母,我們直接存入結果中,如果是數字,我們迴圈讀入所有的數字,並正確轉換,那麼下一位非數字的字元一定是左中括號,我們指標右移跳過左中括號,對之後的內容呼叫遞迴函式求解,注意我們迴圈的停止條件是遍歷到末尾和遇到右中括號,由於遞迴呼叫的函式返回了子中括號裡解碼後的字串,而我們之前把次數也已經求出來了,那麼迴圈新增到結果中即可,參見程式碼如下:

class Solution {
public:
    string decodeString(string s) {
        int i = 0;
        return decode(s, i);
    }
    string decode(string s, int& i) {
        string res = "";
        int n = s.size();
        while (i < n && s[i] != ']') {
            if (s[i] < '0' || s[i] > '9') {
                res += s[i++];
            } else {
                int cnt = 0;
                while (i < n && s[i] >= '0' && s[i] <= '9') {
                    cnt = cnt * 10 + s[i++] - '0';
                }
                ++i;
                string t = decode(s, i);
                ++i;
                while (cnt-- > 0) {
                    res += t;
                }
            }
        }
        return res;
    }
};

我們也可以用迭代的方法寫出來,當然需要用stack來輔助運算,我們用兩個stack,一個用來儲存個數,一個用來儲存字串,我們遍歷輸入字串,如果遇到數字,我們更新計數變數cnt;如果遇到左中括號,我們把當前cnt壓入數字棧中,把當前t壓入字串棧中;如果遇到右中括號時,我們取出數字棧中頂元素,存入變數k,然後給字串棧的頂元素迴圈加上k個t字串,然後取出頂元素存入字串t中;如果遇到字母,我們直接加入字串t中即可,參見程式碼如下:

class Solution {
public:
    string decodeString(string s) {
        string res = "", t = "";
        stack<int> s_num;
        stack<string> s_str;
        int cnt = 0;
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] >= '0' && s[i] <= '9') {
                cnt = 10 * cnt + s[i] - '0';
            } else if (s[i] == '[') {
                s_num.push(cnt);
                s_str.push(t);
                cnt = 0; t.clear();
            } else if (s[i] == ']') {
                int k = s_num.top(); s_num.pop();
                for (int j = 0; j < k; ++j) s_str.top() += t;
                t = s_str.top(); s_str.pop();
            } else {
                t += s[i];
            }
        }
        return s_str.empty() ? t : s_str.top(); //正常輸入格式下,s_str是空的,可以直接輸出t.
    }
};

筆記:call back,考察遞迴迭代兩種程式設計方式,題目比較典型。