• 【二叉树】重建二叉树


    leetcode105

    通过二叉树的先序和中序,或者中和后序遍历可以重建这棵二叉树。(已经先序和后序遍历并不能重构唯一的二叉树)

    由先序遍历可以找出二叉树的根节点的值,再去中序/后序遍历中将节点分为左子树和右子树的节点。

    一般地,有迭代和递归两种方法去重建一棵二叉树。递归比较耗时,而且确定边界时容易出错,以下代码采用迭代,时间复杂度O(n),n为树节点数。

    参照先序遍历的迭代的思想,总是把左子树的左节点优先push入栈。
    当栈顶元素s.top() == inorder[0]时,则说明已到达树的最左的叶子节点,随后按照先序遍历迭代思想,转向右子树。
    这里设置了一个flag标志位,flag = 1转向右子树,默认flag=0持续将左子树左节点入栈。

     1 /**
     2  * Definition for binary tree
     3  * struct TreeNode {
     4  *     int val;
     5  *     TreeNode *left;
     6  *     TreeNode *right;
     7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     8  * };
     9  */
    10 //用迭代的方法替换递归
    11 class Solution {
    12 public:
    13     struct TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> in) {
    14         if (pre.size() == 0 || in.size() == 0)
    15             return NULL;
    16         stack<TreeNode *> s;
    17         int i = 0; //pre的index
    18         int j = 0; //in的index
    19         int flag = 0; //flag = 1转向右子树
    20         TreeNode *root = new TreeNode(pre[i]);
    21         TreeNode *temp = root;
    22         s.push(temp);
    23         i++; //push一个,则i++
    24         while (i < pre.size()){
    25             if (!s.empty() && s.top()->val == in[j]){
    26                 temp = s.top();
    27                 s.pop();
    28                 flag = 1;
    29                 j++;
    30             }else{
    31                 if (flag == 0){
    32                     temp->left = new TreeNode(pre[i]);
    33                     temp = temp->left;
    34                     s.push(temp);
    35                     i++;
    36                 }else{
    37                     flag = 0;
    38                     temp->right = new TreeNode(pre[i]);
    39                     temp = temp->right;
    40                     s.push(temp);
    41                     i++;
    42                 }
    43             }
    44         }
    45        return root;
    46     }
    47 };

    下面是已经中序和后序遍历,重构二叉树。

    leetcode Construct Binary Tree from Inorder and Postorder

    非递归思路来自于https://leetcode.com/discuss/15115/my-comprehension-of-o-n-solution-from-%40hongzhi

    首先明白,后序遍历的最后一个节点的值是二叉树的根节点的值;后序遍历是左——右——根。

    从后往前遍历后序和中序的节点,如果栈顶节点的值等于中序遍历尾节点,则持续将其从中序中pop_back()以及栈中pop出来,因为前面后序中已经遍历过;如果不是,则继续从后往前遍历后序节点,作为栈顶的右孩子,同时入栈。

    //已知中序和后序遍历重构二叉树
    #include <iostream>
    #include <vector>
    #include <stack>
    
    using namespace std;
    
    struct TreeNode{
        int val;
        TreeNode *left, *right;
        TreeNode(int x): val(x), left(NULL), right(NULL){}
    };
    
    TreeNode *constructBinaryTree(vector<int> inorder, vector<int> postorder){
        if (inorder.size() == 0 || postorder.size() == 0){
            return NULL;
        }
        TreeNode *root = new TreeNode(postorder.back());
        postorder.pop_back();
        stack<TreeNode *> s;
        s.push(root);
        TreeNode *temp;
        while (1){
            if (inorder.back() == s.top()->val){
                temp = s.top(); //中序与后序相同的元素,保留最后一个根节点
                s.pop();
                inorder.pop_back();
                if (inorder.size() == 0) break; //pop完后检查inorder.size()
                if (!s.empty() && inorder.back() == s.top()->val) continue; //退出本次循环,下面语句不会执行
                temp->left = new TreeNode(postorder.back());
                postorder.pop_back();
                s.push(temp->left);
            } else{
                temp = new TreeNode(postorder.back());
                postorder.pop_back();
                s.top()->right = temp;
                s.push(temp);
            }
        }
        return root;
    }
    
    int main(){
        vector<int> inorder{4, 2, 5, 1, 3, 6};
        vector<int> postorder{4, 5, 2, 6, 3, 1};
        TreeNode *root = constructBinaryTree(inorder, postorder);
        cout << root->left->val << " " << root->right->val;
        return 0;
    }
  • 相关阅读:
    概率论基础
    感知机
    CSS3实现jquery的特效
    有品质的生活
    table点击一行显示下一行的特效
    colspan在浏览器中失效的问题
    css的框架——common.css
    使用 document.onreadystatechange()来判断页面加载完
    iframe中子页面通过js计算高度(使得页面不会显示不全)
    js返回上一页并刷新的多种方法
  • 原文地址:https://www.cnblogs.com/cnblogsnearby/p/4737599.html
Copyright © 2020-2023  润新知