leetcode1028. 从先序遍历还原二叉树/先序遍历

题目:leetcode1028. 从先序遍历还原二叉树

我们从二叉树的根节点 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 之间。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/recover-a-tree-from-preorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

基本思想1:先序遍历非递归形式

  • 先将字符串分割好,按照节点的值和节点的深度进行分割
  • 先序遍历非递归形式遍历二叉树,借助栈保存节点和节点的深度
/**
 * 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.length() == NULL)
            return NULL;
        //分隔字符串
        int j = 0, lev = 0, num = 0;
        vector<int> nums;
        vector<int> level;
        while(j < S.length()){
            lev = 0;
            while(j < S.length() && S[j] == '-'){
                ++lev;
                ++j;
            }
            level.push_back(lev);
            
            num = 0;
            while(j < S.length() && S[j] != '-'){
                num = num * 10 + S[j] - '0';
                ++j;
            }
            nums.push_back(num);            
        }
        
        //构造二叉树
        TreeNode * root, *p;
        p = new TreeNode(nums[0]);
        root = p;
        j = 1;
        stack<TreeNode*> st;
        stack<int> stl;//保存节点的深度
        st.push(root);
        stl.push(0);
        int l;
        while(j < nums.size()){
            while(j < nums.size() && level[j] > level[j - 1]){                
                p->left = new TreeNode(nums[j]);
                p = p->left;
                st.push(p);
                stl.push(level[j]);
                ++j;
            }
            l = stl.top();            
            st.pop();
            stl.pop();
            if(j < nums.size() && level[j] == l){
                p = st.top();
                p->right = new TreeNode(nums[j]);
                p = p->right;
                st.push(p);
                stl.push(level[j]);
                ++j;
            }
            
            
        }
        return root;
    }
};

基本思想2:先序遍历递归形式

递归形式的关键是:如何划分左右子树。
注意: 题目中指名如果只有一个子节点,那么这个节点是左子节点
划分左右子树的方法:当前节点的下一个节点(如果存在)一定是当前节点的左子节点,寻找当前与当前的左字节点相同深度的节点就是右子树的先序遍历的第一个节点

/**
 * 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> nums;
    vector<int> level;
public:
    TreeNode* recoverFromPreorder(string S) {
        if(S.length() == NULL)
            return NULL;
        //分隔字符串
        int j = 0, lev = 0, num = 0;
        
        while(j < S.length()){
            lev = 0;
            while(j < S.length() && S[j] == '-'){
                ++lev;
                ++j;
            }
            level.push_back(lev);
            
            num = 0;
            while(j < S.length() && S[j] != '-'){
                num = num * 10 + S[j] - '0';
                ++j;
            }
            nums.push_back(num);            
        }
        
        return create(0, nums.size() - 1);
    }
    TreeNode* create(int l, int r){
        if(l > r)
            return NULL;
        TreeNode* root = new TreeNode(nums[l]);
        if(l + 1 <= r){
            int i = l + 2;
            while(i <= r && level[i] != level[l + 1]){
                ++i;
            }
            root->left = create(l + 1, i - 1);
            root->right = create(i, r);
        }
        
        
        return root;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章