前言
前两周因为雅思考试和学校里繁重课业没有跟新,现在继续每日至少一题!
思考
查理芒格说过一定要记住反着想!这道题就是让我们从一个通过先序遍历生成的字符串来还原二叉树,那么我们反过来想,应该如何通过二叉树来生成字符串呢?通过观察示例,我们发现在root->val之前的’-'的数量就代表了这个节点在树中的高度或层数,那么生成的方法应该是这样的:
// 伪代码
string S;
void preOrder(TreeNode* root, int height) {
for(int i = 0; i < height; i++) {
S+='-'; // 拼接层数
S+=string(root->val); // 将root的值拼接倒字符串上
preOrder(root->left, height+1);
preOrder(root->right, height+1);
}
因此,如果我们想要构造出字符串,我们就应在对应的高度消除root值前面的’-’,然后读入对应的root->val,这就是代码的思路了!
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
string temp;
TreeNode* recoverFromPreorder(string S) {
TreeNode* root = nullptr;
TreeNode* head = new TreeNode(); // 定义一个哑结点(头节点)(head)
temp=S;
preOrder(root, head, true, 0);
return head->left;
}
void preOrder(TreeNode* root, TreeNode* parent, bool left, int height) {
/**
* root: 要构造的当前root
* parent: root的parent
* left: 区别是左孩子还是右孩子,left=true代表左孩子,反之代表右孩子
* height: 高度
*/
if(temp.empty()) // 如果字符串为空,那么说明都添加完成了,就直接返回
return;
for(int i = 0; i < height; i++) {
if(temp[i] != '-') // 如果中间有出现不是'-'的情况,就说明height超过了,这个节点是空,直接返回
return;
}
// 删除节点前面的所有'-'(也可以放在上面的for循环遍历一次删除一个)
temp.erase(0,height);
// cout << temp << endl;
// 将字符串表示的数字转为int
int length = 0;
int total = 0;
// cout << temp.size() << endl;
while(temp[length] != '-') {
total = total * 10 + int(temp[length])-48;
length++;
if(length == temp.size())
break;
}
// 建当前的root,并添加root->val
root = new TreeNode(total);
// 将父节点和子节点连起来
if(left){
parent->left = root;
} else {
parent->right = root;
}
// 删除当前root->val对应的字符串
temp.erase(0,length);
// cout << temp << ", root->val = " << root->val << endl;
//前序遍历
preOrder(root->left, root, true, height+1);
preOrder(root->right, root, false, height+1);
}
};