You need to construct a binary tree from a string consisting of parenthesis and integers.
The whole input represents a binary tree. It contains an integer followed by zero, one or two pairs of parenthesis. The integer represents the root's value and a pair of parenthesis contains a child binary tree with the same structure.
You always start to construct the left child node of the parent first if it exists.
Example:
Input: "4(2(3)(1))(6(5))" Output: return the tree root node representing the following tree: 4 / \ 2 6 / \ / 3 1 5
Note:
- There will only be
'('
,')'
,'-'
and'0'
~'9'
in the input string. - An empty tree is represented by
""
instead of"()"
.
這道題讓我們根據一個字符串來創建一個二叉樹,其中結點與其左右子樹是用括號隔開,每個括號中又是數字后面的跟括號的模式,這種模型就很有遞歸的感覺,所以我們當然可以使用遞歸來做。首先我們要做的是先找出根結點值,我們找第一個左括號的位置,如果找不到,說明當前字符串都是數字,直接轉化為整型,然后新建結點返回即可。否則的話從當前位置開始遍歷,因為當前位置是一個左括號,我們的目標是找到與之對應的右括號的位置,但是由於中間還會遇到左右括號,所以我們需要用一個變量 cnt 來記錄左括號的個數,如果遇到左括號,cnt 自增1,如果遇到右括號,cnt 自減1,這樣當某個時刻 cnt 為0的時候,我們就確定了一個完整的子樹的位置,那么問題來了,這個子樹到底是左子樹還是右子樹呢,我們需要一個輔助變量 start,當最開始找到第一個左括號的位置時,將 start 賦值為該位置,那么當 cnt 為0時,如果 start 還是原來的位置,說明這個是左子樹,我們對其調用遞歸函數,注意此時更新 start 的位置,這樣就能區分左右子樹了,參見代碼如下:
解法一:
class Solution { public: TreeNode* str2tree(string s) { if (s.empty()) return NULL; auto found = s.find('('); int val = (found == string::npos) ? stoi(s) : stoi(s.substr(0, found)); TreeNode *cur = new TreeNode(val); if (found == string::npos) return cur; int start = found, cnt = 0; for (int i = start; i < s.size(); ++i) { if (s[i] == '(') ++cnt; else if (s[i] == ')') --cnt; if (cnt == 0 && start == found) { cur->left = str2tree(s.substr(start + 1, i - start - 1)); start = i + 1; } else if (cnt == 0) { cur->right = str2tree(s.substr(start + 1, i - start - 1)); } } return cur; } };
下面這種解法使用迭代來做的,借助棧 stack 來實現。遍歷字符串s,用變量j記錄當前位置i,然后看當前遍歷到的字符是什么,如果遇到的是左括號,什么也不做繼續遍歷;如果遇到的是數字或者負號,那么我們將連續的數字都找出來,然后轉為整型並新建結點,此時我們看 stack 中是否有結點,如果有的話,當前結點就是棧頂結點的子結點,如果棧頂結點沒有左子結點,那么此結點就是其左子結點,反之則為其右子結點。之后要將此結點壓入棧中。如果我們遍歷到的是右括號,說明棧頂元素的子結點已經處理完了,將其移除棧,參見代碼如下:
解法二:
class Solution { public: TreeNode* str2tree(string s) { if (s.empty()) return NULL; stack<TreeNode*> st; for (int i = 0; i < s.size(); ++i) { int j = i; if (s[i] == ')') st.pop(); else if ((s[i] >= '0' && s[i] <= '9') || s[i] == '-') { while (i + 1 < s.size() && s[i + 1] >= '0' && s[i + 1] <= '9') ++i; TreeNode *cur = new TreeNode(stoi(s.substr(j, i - j + 1))); if (!st.empty()) { TreeNode *t = st.top(); if (!t->left) t->left = cur; else t->right = cur; } st.push(cur); } } return st.top(); } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/536
類似題目:
Construct String from Binary Tree
參考資料:
https://leetcode.com/problems/construct-binary-tree-from-string/
https://leetcode.com/problems/construct-binary-tree-from-string/discuss/100359/Java-stack-solution