問題描述
我們從二叉樹的根節點 root 開始進行深度優先搜索。
在遍歷中的每個節點處,我們輸出 D 條短劃線(其中 D 是該節點的深度),然後輸出該節點的值。(如果節點的深度爲 D,則其直接子節點的深度爲 D + 1。根節點的深度爲 0)。
如果節點只有一個子節點,那麼保證該子節點爲左子節點。
給出遍歷輸出 S,還原樹並返回其根節點 root。
輸入:“1-2- -3- -4-5- -6- -7”
輸出:[1,2,5,3,4,6,7]
解題報告
模擬先序遍歷進行反序列化。
通過讀取 當前元素所屬 - 個數
【該元素前面 -
的個數】 和 棧中元素個數
大小關係 比較得出是否應該回溯。
當前元素所屬 - 個數
和棧中元素個數
相等時,說明繼續向左子樹迭代,當前元素是棧頂元素的左子樹當前元素所屬 - 個數
比棧中元素個數
小時,說明該回溯了,將棧中元素彈出,直到當前元素所屬 - 個數
和棧中元素個數
相等,此時當前元素即爲棧頂元素的右子樹。當前元素所屬 - 個數
不會比棧中元素個數
大,因爲 1)不回溯時,-
每增加一個,就有一個元素入棧,【字符串的第一個數字對應的-
爲零】;2)當前元素所屬 - 個數
比棧中元素個數
小時纔會回溯。
這道題有點像二叉樹的反序列化 Leetcode 297. 二叉樹的序列化和反序列化,但是如果不是在題目限制的情況下【如果節點只有一個子節點,那麼保證孩子節點爲左子節點】,我們僅根據這樣的先序遍歷還是無法確定一個二叉樹的。
總是不會實現自己的思想,看到別人的代碼才知道原來可以這樣實現啊,這是一個大問題。
實現代碼
class Solution {
public:
TreeNode* recoverFromPreorder(string S) {
stack<TreeNode*> path;
int pos = 0;
while (pos < S.size()) {
int level = 0;
while (S[pos] == '-') {
++level;
++pos;
}
int value = 0;
while (pos < S.size() && isdigit(S[pos])) {
value = value * 10 + (S[pos] - '0');
++pos;
}
TreeNode* node = new TreeNode(value);
if (level == path.size()) {
if (!path.empty()) {
path.top()->left = node;
}
}
else {
// 當前節點的層數比棧中節點還要長,則說明需要開始回溯
while (level != path.size()) path.pop();
path.top()->right = node;
}
path.push(node);
}
while (path.size() > 1) {
cout<<path.top()->val<<" ";
path.pop();
}
return path.top();
}
};
// 作者:LeetCode-Solution
// 鏈接:https://leetcode-cn.com/problems/recover-a-tree-from-preorder-traversal/solution/cong-xian-xu-bian-li-huan-yuan-er-cha-shu-by-leetc/
// 來源:力扣(LeetCode)
// 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
參考資料
[1] Leetcode 1028. 從先序遍歷還原二叉樹
[2] 官方題解