1. 程式人生 > >LeetCode385. 迷你語法分析器(Mini P)

LeetCode385. 迷你語法分析器(Mini P)

題目描述

給定一個用字串表示的整數的巢狀列表,實現一個解析它的語法分析器。
列表中的每個元素只可能是整數或整數巢狀列表
提示:
你可以假定這些字串都是格式良好的:
字串非空
字串不包含空格
字串只包含數字0-9 [ - , ]
示例 1:

給定 s = "324",
你應該返回一個 NestedInteger 物件,其中只包含整數值 324。

示例 2:

給定 s = "[123,[456,[789]]]",
返回一個 NestedInteger 物件包含一個有兩個元素的巢狀列表:
1. 一個 integer 包含值 123
2. 一個包含兩個元素的巢狀列表:
    i.  一個 integer 包含值 456
    ii. 一個包含一個元素的巢狀列表
         a. 一個 integer 包含值 789

再理題意:

  • 對於NestedInteger(),建構函式初始化一個空的巢狀列表。
  • 對於NestedInteger(int value),建構函式初始化一個整數。
  • 對於bool isInteger() const,如果此NestedInteger包含單個整數而不是巢狀列表,則返回true。
  • 對於int getInteger() const,返回此NestedInteger儲存的單個整數(如果它包含單個整數),如果此NestedInteger包含巢狀列表,則結果未定義。
  • 對於void setInteger(int value),設定此NestedInteger以儲存單個整數。
  • 對於void add(const NestedInteger &ni),設定此NestedInteger以儲存巢狀列表並向其新增巢狀整數。
  • 對於const vector< NestedInteger> &getList() const,如果它擁有巢狀列表,則返回此NestedInteger包含的巢狀列表,如果此NestedInteger包含單個整數,則結果未定義。

遞迴解法思路:

  1. 首先判斷s是否為空,為空直接返回;
  2. s不為空的話看首字元是否為’[’,不是的話說明s為一個整數,我們直接返回結果。
  3. 如果s中首字元是’[’,且s長度小於等於2,說明沒有內容,直接返回結果。(’[‘或’[]’)
  4. 如果s長度大於2,我們從i=1開始遍歷,我們需要一個變數start來記錄某一層的真實位置,用cnt來記錄跟真實位置是否為同一深度,cnt=0表示同一深度,由於中間每段都是由逗號隔開,所以當我們判斷當cnt為0,且當前字元是逗號或者已經到字串末尾了,我們把start到當前位置之間的字串取出來遞迴呼叫函式,把返回結果加入res中,然後start更新為i+1。如果遇到’[’,計數器cnt自增1,若遇到’]’,計數器cnt自減1。
    遞迴解法程式碼:
/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * class NestedInteger {
 *   public:
 *     // Constructor initializes an empty nested list.
 *     NestedInteger(); 建構函式初始化一個空的巢狀列表
 *
 *     // Constructor initializes a single integer.
 *     NestedInteger(int value);建構函式初始化一個整數。
 *
 *     // Return true if this NestedInteger holds a single integer, rather than a nested list.
 *     bool isInteger() const;如果此NestedInteger包含單個整數而不是巢狀列表,則返回true。
 *
 *     // Return the single integer that this NestedInteger holds, if it holds a single integer
 *     // The result is undefined if this NestedInteger holds a nested list
 *     int getInteger() const;返回此NestedInteger儲存的單個整數(如果它包含單個整數),如果此NestedInteger包含巢狀列表,則結果未定義。
 *
 *     // Set this NestedInteger to hold a single integer.
 *     void setInteger(int value);設定此NestedInteger以儲存單個整數。
 *
 *     // Set this NestedInteger to hold a nested list and adds a nested integer to it.
 *     void add(const NestedInteger &ni);設定此NestedInteger以儲存巢狀列表並向其新增巢狀整數。
 *
 *     // Return the nested list that this NestedInteger holds, if it holds a nested list
 *     // The result is undefined if this NestedInteger holds a single integer
 *     const vector<NestedInteger> &getList() const;如果它擁有巢狀列表,則返回此NestedInteger包含的巢狀列表,如果此NestedInteger包含單個整數,則結果未定義。
 * };
 */
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函式加入新的棧頂元素中以實現巢狀。
非遞迴解法程式碼:

/**
 * // This is the interface that allows for creating nested lists.
 * // You should not implement it, or speculate about its implementation
 * class NestedInteger {
 *   public:
 *     // Constructor initializes an empty nested list.
 *     NestedInteger(); 建構函式初始化一個空的巢狀列表
 *
 *     // Constructor initializes a single integer.
 *     NestedInteger(int value);建構函式初始化一個整數。
 *
 *     // Return true if this NestedInteger holds a single integer, rather than a nested list.
 *     bool isInteger() const;如果此NestedInteger包含單個整數而不是巢狀列表,則返回true。
 *
 *     // Return the single integer that this NestedInteger holds, if it holds a single integer
 *     // The result is undefined if this NestedInteger holds a nested list
 *     int getInteger() const;返回此NestedInteger儲存的單個整數(如果它包含單個整數),如果此NestedInteger包含巢狀列表,則結果未定義。
 *
 *     // Set this NestedInteger to hold a single integer.
 *     void setInteger(int value);設定此NestedInteger以儲存單個整數。
 *
 *     // Set this NestedInteger to hold a nested list and adds a nested integer to it.
 *     void add(const NestedInteger &ni);設定此NestedInteger以儲存巢狀列表並向其新增巢狀整數。
 *
 *     // Return the nested list that this NestedInteger holds, if it holds a nested list
 *     // The result is undefined if this NestedInteger holds a single integer
 *     const vector<NestedInteger> &getList() const;如果它擁有巢狀列表,則返回此NestedInteger包含的巢狀列表,如果此NestedInteger包含單個整數,則結果未定義。
 * };
 */
class Solution {
public:
    NestedInteger deserialize(string s) {
        if(s.empty()) return NestedInteger();
        if(s[0]!='[') return NestedInteger(stoi(s));
        stack<NestedInteger> res;
        int start=1;
        for(int i=0;i<s.size();i++){
            if(s[i]=='[') {
                res.push(NestedInteger());
                start=i+1;
            }
            else if(s[i]==','||s[i]==']'){
                if(i>start) res.top().add(stoi(s.substr(start,i-start)));
                start=i+1;
                if(s[i]==']') {
                    if(res.size()>1) {
                        NestedInteger temp=res.top();res.pop();
                        res.top().add(temp);
                    }
                }
            }
        }
        return res.top();
    }
};