(树,递归)重建二叉树,二叉树的下一个结点

 

 

树的数据结构:

 

 

 

重建二叉树

链接:https://www.nowcoder.com/questionTerminal/8a19cbe657394eeaac2f6ea9b0f6fcf6
来源:牛客网

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

 

前序遍历的第一个节点就是树的根节点,所以我们先根据前序遍历序列的第一个数字创建根结点,接下来在中序遍历序列中找到根结点的位置,根节点的左边就是左子树,右边就是右子树,这样就能确定左、右子树结点的数量。在前序遍历和中序遍历的序列中划分了左、右子树结点的值之后,就可以递归地去分别构建它的左右子树。

 

 

 

 

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        int p = pre.size();
        int v = vin.size();
        if(p<=0 || v<=0) return NULL;
        return construct(pre, vin, 0, p-1, 0, v-1);
    }
    
    TreeNode* construct(vector<int>& pre, vector<int>& vin, int st_p, int ed_p, int st_v, int ed_v){
        if(st_p>ed_p || st_v>ed_v) return NULL;
        TreeNode* root = new TreeNode(pre[st_p]);
        for(int i=st_v; i<=ed_v; i++){  //在中序遍历中找到根结点
            if(vin[i] == pre[st_p]){   
                root->left = construct(pre, vin, st_p+1, st_p+i-st_v, st_v, i-1);
                root->right = construct(pre, vin, st_p+i-st_v+1, ed_p, i+1, ed_v);
                break;
            }
        }
        return root;
    }
};

 

 

一颗完全二叉树的节点数量为666,那么这棵树上的叶子节点数为  333

 

链接:https://www.nowcoder.com/questionTerminal/4e2380083eb0483592d5312703d2dfe6
来源:牛客网

设这个完全二叉树有K层,前K-1层有2^9-1=511个节点,最后一层有666-511=155个全是叶子节点;
倒数第二层有2^8=256个节点,其中155/2=77个有两个孩子,第78个有一个孩子,剩256-78=178个叶子节点;
155+178=333个 

 

 公式:完全二叉树叶子节点数=向上取整

 

 

二叉树的下一个结点 

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

https://www.nowcoder.com/questionTerminal/9023a0c988684a53960365b889ceaf5e
 
做法:三种情况:
1)一个结点有右子树,则它的下一个结点是它的右子树中的最左结点。如b的下一个结点是h
 
2)一个结点没有右子树,但这个结点时它父结点的左结点时,则它的下一结点是它父结点。如d的下一个结点是b。
3)一个结点没有右子树,且这个结点时它父结点的右结点时,沿着它父结点指针一直向上遍历,直到找到第一个当前节点是父节点左孩子的节点,则这个结点的父结点就是要找的下一个结点。
下面代码把2,3两种情况合并了。
/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {
        if(pNode==NULL) return NULL;
        
        if(pNode->right){
            // 一个结点有右子树,则它的下一个结点是它的右子树中的最左结点
            TreeLinkNode* t1 = pNode->right;
            while(t1->left){
                t1 = t1->left;
            }
            return t1;
        }
        while(pNode->next){
            if(pNode->next->left == pNode) 
                return pNode->next;
            pNode = pNode->next;
        }
        return NULL;
    }
};

 

posted @ 2019-11-08 17:17  爱学英语的程序媛  阅读(183)  评论(0编辑  收藏  举报