[LeetCode] Mini Parser 迷你解析器


 

Given a nested list of integers represented as a string, implement a parser to deserialize it.

Each element is either an integer, or a list -- whose elements may also be integers or other lists.

Note: You may assume that the string is well-formed:

  • String is non-empty.
  • String does not contain white spaces.
  • String contains only digits 0-9[- ,].

 

Example 1:

Given s = "324",

You should return a NestedInteger object which contains a single integer 324.

 

Example 2:

Given s = "[123,[456,[789]]]",

Return a NestedInteger object containing a nested list with 2 elements:

1. An integer containing value 123.
2. A nested list containing two elements:
    i.  An integer containing value 456.
    ii. A nested list with one element:
         a. An integer containing value 789.

 

這道題讓我們實現一個迷你解析器用來把一個字符串解析成NestInteger類,關於這個嵌套鏈表類的題我們之前做過三道,Nested List Weight Sum IIFlatten Nested List Iterator,和Nested List Weight Sum。應該對這個類並不陌生了,我們可以先用遞歸來做,思路是,首先判斷s是否為空,為空直接返回,不為空的話看首字符是否為'[',不是的話說明s為一個整數,我們直接返回結果。如果首字符是'[',且s長度小於等於2,說明沒有內容,直接返回結果。反之如果s長度大於2,我們從i=1開始遍歷,我們需要一個變量start來記錄某一層的其實位置,用cnt來記錄跟其實位置是否為同一深度,cnt=0表示同一深度,由於中間每段都是由逗號隔開,所以當我們判斷當cnt為0,且當前字符是逗號或者已經到字符串末尾了,我們把start到當前位置之間的字符串取出來遞歸調用函數,把返回結果加入res中,然后start更新為i+1。如果遇到'[',計數器cnt自增1,若遇到']',計數器cnt自減1。參見代碼如下:

 

解法一:

class Solution {
public:
    NestedInteger deserialize(string s) {
        if (s.empty()) return NestedInteger();
        if (s[0] != '[') return NestedInteger(stoi(s));
        if (s.size() <= 2) return NestedInteger();
        NestedInteger res;
        int start = 1, cnt = 0;
        for (int i = 1; i < s.size(); ++i) {
            if (cnt == 0 && (s[i] == ',' || i == s.size() - 1)) {
                res.add(deserialize(s.substr(start, i - start)));
                start = i + 1;
            } else if (s[i] == '[') ++cnt;
            else if (s[i] == ']') --cnt;
        }
        return res;
    }
};

 

我們也可以使用迭代的方法來做,這樣就需要使用棧來輔助,變量start記錄起始位置,我們遍歷字符串,如果遇到'[',我們給棧中加上一個空的NestInteger,如果遇到的字符數逗號或者']',如果i>start,那么我們給棧頂元素調用add來新加一個NestInteger,初始化參數傳入start到i之間的子字符串轉為的整數,然后更新start=i+1,當遇到的']'時,如果此時棧中元素多於1個,那么我們將棧頂元素取出,加入新的棧頂元素中通過調用add函數,參見代碼如下:
 
解法二:
class Solution {
public:
    NestedInteger deserialize(string s) {
        if (s.empty()) return NestedInteger();
        if (s[0] != '[') return NestedInteger(stoi(s));
        stack<NestedInteger> st;
        int start = 1;
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] == '[') {
                st.push(NestedInteger());
                start = i + 1;
            } else if (s[i] == ',' || s[i] == ']') {
                if (i > start) {
                    st.top().add(NestedInteger(stoi(s.substr(start, i - start))));
                }
                start = i + 1;
                if (s[i] == ']') {
                    if (st.size() > 1) {
                        NestedInteger t = st.top(); st.pop();
                        st.top().add(t);
                    }
                }
            }
        }
        return st.top();
    }
};

 

還有一種方法是利用C++ STL中的字符串流處理類istringstream,我們需要對幾個函數有些了解,比如clear()是重置字符流中的字符串,get()是獲得下一個字符,peek()是返回首字符,>>num是讀取出合法的整數,如果無法讀取出整數,需要調用clear()來重置字符串,否則調用get()會出錯。思路跟上面的遞歸解法相同,參見代碼如下:

 

解法三:

class Solution {
public:
    NestedInteger deserialize(string s) {
        istringstream in(s);
        return deserialize(in);
    }
    NestedInteger deserialize(istringstream& in) {
        int num;
        if (in >> num) return NestedInteger(num);
        in.clear();
        in.get();
        NestedInteger list;
        while (in.peek() != ']') {
            list.add(deserialize(in));
            if (in.peek() == ',') {
                in.get();
            }
        }
        in.get();
        return list;
    }
};

 

類似題目:

Nested List Weight Sum II

Flatten Nested List Iterator

Nested List Weight Sum

 

參考資料:

https://discuss.leetcode.com/topic/54258/python-c-solutions/3

https://discuss.leetcode.com/topic/54341/iterative-c-using-stack

https://discuss.leetcode.com/topic/54277/short-java-recursive-solution

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM