1028. 从先序遍历还原二叉树
我们从二叉树的根节点 root 开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S,还原树并返回其根节点 root。
示例 1:
输入:"1-2--3--4-5--6--7"
输出:[1,2,5,3,4,6,7]
示例 2:
输入:"1-2--3---4-5--6---7"
输出:[1,2,5,3,null,6,null,4,null,7]
示例 3:
输入:"1-401--349---90--88"
输出:[1,401,null,349,88,90]
提示:
原始树中的节点数介于 1 和 1000 之间。
每个节点的值介于 1 和 10 ^ 9 之间。
递归+DFS
全局变量i记录当前遍历的位置;
(1)获取当前节点,若不能作为左子树,则还原i,返回上一层;
(2)若能做左子树,放入左子树位置;看后面是否有右子树,无则递归左子树的子树;
(3)若还有右子树,则左子树无子树,放入右子树后递归右子树的子树;
每次判断完都需要还原i;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* recoverFromPreorder(string S) {
if(!S.size()) return NULL;
i=0;
int num=cal(S);
TreeNode * root = new TreeNode(num);
buildtree(S,0,root);
return root;
}
private:
int i; //用于遍历字符串
void buildtree(string S,int n,TreeNode * root){
int cnt=0;
int t=i;
while(S[i]=='-'){i++; cnt++;} //若写在while里面,非判断也会让i++
if(cnt==n+1){ //若有左子节点
int tmp=cal(S);
root->left=new TreeNode(tmp); //放入左边
cnt=0;
t=i;
while(S[i]=='-') {i++;cnt++;}
if(cnt==n+1){ //若有右子节点
int tmp=cal(S);
root->right=new TreeNode(tmp); //放入右边
buildtree(S,n+1,root->right); //往后递归
}else if (cnt>n+1){ //若无右子节点,但有节点
i=t;
buildtree(S,n+1,root->left);//往左边递归
//左边建树完成
cnt=0;
t=i;
while(S[i]=='-'){i++; cnt++;} //检查右子树
if(cnt==n+1){ //若有右子树
tmp=cal(S);
root->right=new TreeNode(tmp);
buildtree(S,n+1,root->right); //进入右子树递归
}else i=t; //若无右子树
}else i=t;
}else i=t;
return;
}
int cal(string S){
int res=0;
while(isdigit(S[i])){
res=res*10+(S[i++]-'0');
}
return res;
}
};
迭代+堆栈
关键点:
栈内节点数量为当前构造的深度;
每次得到新节点,赋给栈顶元素;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* recoverFromPreorder(string S) {
if(!S.size()) return NULL; //确定S大小
stack<TreeNode*> T; //建立堆栈
i=0; //从头开始遍历S
int tmp=calnum(S); //将根节点入栈
TreeNode* root=new TreeNode(tmp);
T.push(root);
while(i<S.size()){ //遍历S
int len=calflr(S); //计算当前节点深度
int num=calnum(S); //计算当前节点数值
TreeNode * newnode=new TreeNode(num); //构造当前节点
while(len<T.size()) T.pop(); //若当前节点深度小于栈内节点数量,栈内节点出栈
TreeNode * temp=T.top(); //取出栈顶元素
if(!temp->left) temp->left=newnode; //先判断栈顶元素有无左子树,无则赋值
else temp->right=newnode; //有则右子树赋值
T.push(newnode); //新节点入队
}
return root;
}
private:
int i;
int calnum(string S){
int res=0;
while(isdigit(S[i])) res=res*10+S[i++]-'0';
return res;
}
int calflr(string S){
int cnt=0;
while(i<S.size()&&S[i]=='-') {i++;cnt++;}
return cnt;
}
};