每日一题,防止痴呆 = =
一、题目大意
我们从二叉树的根节点 root 开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S,还原树并返回其根节点 root。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/recover-a-tree-from-preorder-traversal
二、题目思路以及AC代码
思路
对于普通的先序遍历,我们知道是无法还原成唯一的二叉树的,但是本题给了每个节点的深度,同时规定如果某个节点只有一个子节点,那么该子节点一定是左子节点,这也就使得这种先序遍历是可以唯一表达一棵二叉树的。
思路其实同先序和中序恢复二叉树类似,肯定是用递归来实现。我们可以先把题目给定的先序序列处理一下,比如 “1-2–3--4-5–6--7”,我们可以将其处理为一个值数组和一个深度数组,并且一一对应,也就是 val: [1, 2, 3, 4, 5, 6, 7]; depth: [0, 1, 2, 2, 1, 2, 2]。
这样我们在每次递归时,只要找到当前节点两个子节点在数组中的位置,其中左子节点的位置肯定是 l+1,所以我们只需要找右子节点的位置即可,然后对左右两个序列继续递归,将递归结果作为左右指针赋值给当前节点的左右子树,具体可以参见代码。
AC代码
/**
* 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 {
private:
vector<int> val;
vector<int> depth;
public:
TreeNode* recoverTree(int l, int r) {
if (l > r) return NULL;
TreeNode* root = new TreeNode(val[l]);
int d = depth[l];
int left = l + 1, right = r + 1;
if (left > r) return root;
for (int i=left + 1;i<=r;i++) {
if (depth[i] == d+1) {
right = i;
break;
}
}
root->left = recoverTree(left, right - 1);
root->right = recoverTree(right, r);
return root;
}
TreeNode* recoverFromPreorder(string S) {
int len = S.length();
int i = 0;
while (i < len) {
// 找 -
int cnt = 0;
while (i < len && S[i] == '-') {
i++;
cnt++;
}
string tmp = "";
while (i < len && S[i] != '-') {
tmp += S[i++];
}
int value = atoi(tmp.c_str());
val.push_back(value);
depth.push_back(cnt);
}
return recoverTree(0, val.size() - 1);
}
};
如果有问题,欢迎大家指正!!!