LeetCode385. 迷你語法分析器(Mini P)
阿新 • • 發佈:2018-11-14
題目描述
給定一個用字串表示的整數的巢狀列表,實現一個解析它的語法分析器。
列表中的每個元素只可能是整數或整數巢狀列表
提示:
你可以假定這些字串都是格式良好的:
字串非空
字串不包含空格
字串只包含數字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包含單個整數,則結果未定義。
遞迴解法思路:
- 首先判斷s是否為空,為空直接返回;
- s不為空的話看首字元是否為’[’,不是的話說明s為一個整數,我們直接返回結果。
- 如果s中首字元是’[’,且s長度小於等於2,說明沒有內容,直接返回結果。(’[‘或’[]’)
- 如果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();
}
};