leetcode真题——二叉树:106. 从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树 654.最大二叉树

leetcode真题——二叉树:106. 从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树 654.最大二叉树,第1张

文章目录
    • 106. 从中序与后序遍历序列构造二叉树
    • 105.从前序与中序遍历序列构造二叉树
    • 654.最大二叉树

106. 从中序与后序遍历序列构造二叉树

https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

/**
 * 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:
    TreeNode* transfer(vector<int> &inorder,vector<int> &postorder){
        // 分割出空节点,返回
        if(postorder.size()==0) return nullptr;

        // 取出后序的最后一个作为分割点
        int rootValue = postorder[postorder.size() - 1];
        TreeNode *root = new TreeNode(rootValue);

        // 分割到只剩叶子结点,给叶子结点赋值
        if(postorder.size() == 1) return root;
        int i = 0;
        for(; i < inorder.size(); i++){
            if(inorder[i] == rootValue) break;
        }

        // 按照分割点切分中序数组
        vector<int> leftInorder (inorder.begin(), inorder.begin() + i); // [0,i]
        vector<int> rightInorder (inorder.begin() + i + 1, inorder.end()); // [i+1,end]
        
        // 按照中序左右数组的大小切分后序数组
        postorder.resize(postorder.size() - 1);
        vector<int> leftPostorder (postorder.begin(), postorder.begin() + leftInorder.size());
        vector<int> rightPostorder (postorder.begin() + leftInorder.size(), postorder.end());
        
        // 重构树
        root->left = transfer(leftInorder,leftPostorder);
        root->right = transfer(rightInorder,rightPostorder);

        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size()==0 || postorder.size()==0) return nullptr;
        return transfer(inorder,postorder);
    }
};

优化:将递归中创建的中序后序的左右序列数组,替换成用下标定位,节约空间。


/**
 * 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:
    // 这里的inE postE 都是闭区间,相当于size
    TreeNode* transfer(vector<int> &inorder,int inS,int inE,vector<int> &postorder,int postS,int postE){
        // 当前为空节点 返回
        if(postE == postS) return nullptr;

        // 获取分割点
        int rootValue = postorder[postE - 1];
        TreeNode *root = new TreeNode(rootValue);

        if(postE - postS == 1) return root; //叶子结点直接返回

        // 用分割点划分中序数组
        int i = inS;
        for(;i < inE; i++){
            if(inorder[i] == rootValue) break;
        }//分别设置左右数组的下标
        int leftInS = inS;
        int leftInE = i;
        int rightInS = i + 1;
        int rightInE = inE; 

        // 用中序数组的左右序列大小划分后序数组
        int leftPostS = postS;
        int leftPostE = postS + i - inS;
        int rightPostS = postS + i - inS;
        int rightPostE = postE - 1; // 最后一位舍掉
        // 构建树
        root->left = transfer(inorder,leftInS,leftInE,postorder,leftPostS,leftPostE);
        root->right = transfer(inorder,rightInS,rightInE,postorder,rightPostS,rightPostE);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size()==0 || postorder.size()==0) return nullptr;
        return transfer(inorder,0,inorder.size(),postorder,0,postorder.size());
    }
};
105.从前序与中序遍历序列构造二叉树

大致思路类似,把中序和后序的理解清楚然后中序前序就简单多了,只需要将前序序列起始结束的更新变一下即可。



/**
 * 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:
    // 始终保持左闭右开原则
    TreeNode* construct(vector<int> &preorder, int preS, int preE, vector<int>& inorder, int inS, int inE){
        // 此时到达空节点,返回空叶子结点
        if(preE == preS) return nullptr;

        int rootValue = preorder[preS];
        TreeNode *root = new TreeNode(rootValue);
        // 此时序列中只有一个值,说明是叶子结点,直接返回
        if(preE - preS == 1) return root;

        // 根据前序的第一个节点找中序的分割点
        int i;
        for(i = inS; i < inE; i++){
            if(inorder[i] == rootValue) break;
        }

        // 分割中序序列为左右两部分
        int leftInS = inS;
        int leftInE = i;
        int rightInS = i + 1; //跳过根节点
        int rightInE = inE;

        // 根据中序的左右序列分割先序为左右两部分
        preS = preS + 1;
        int leftPreS = preS; // 根被取出来了,跳过根节点
        int leftPreE = preS + i - inS;
        int rightPreS = preS + i - inS;
        int rightPreE = preE;
    
// 打印日志
        // cout<<"--------"<
        // for(int i = leftInS;i
        //     cout<< inorder[i]<<" ";
        // }
        // cout<
        // for(int i = rightInS;i
        //     cout<< inorder[i]<<" ";
        // }
        // cout<
        // for(int i = leftPreS;i
        //     cout<< preorder[i]<<" ";
        // }
        // cout<
        // for(int i = rightPreS;i
        //     cout<< preorder[i]<<" ";
        // }
        // cout<

        // 连接左右子树
        root -> left = construct(preorder,leftPreS,leftPreE,inorder,leftInS,leftInE);
        root -> right = construct(preorder,rightPreS,rightPreE,inorder,rightInS,rightInE);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size() == 0 || inorder.size() == 0) return nullptr;
        return construct(preorder,0,preorder.size(),inorder,0,inorder.size());
    }
};
654.最大二叉树

https://leetcode-cn.com/problems/maximum-binary-tree/

大致思路和构建二叉树一样,但是过程更简单了,就是找左右子树的起始结束位置,然后对其连接再返回根节点。


/**
 * 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:
    TreeNode* construct(vector<int>& num,int s,int e){
    	//到末尾了返回空叶子结点
        if(e == s) return nullptr;
		//找最大值,分割点
        int maxNum = num[s],maxNumIndex=s;
        for(int i = s+1; i < e; i++){
            if(num[i]>maxNum) {
            	maxNum = num[i];
            	maxNumIndex=i;
            }
        }
        TreeNode *root = new TreeNode(maxNum);
        //只有一个元素返回叶子结点
        if(e - 1 == s) return root;
       
        //左子树下标
        int leftS = s;
        int leftE = maxNumIndex;
        //右子树下标
        int rightS = maxNumIndex + 1;
        int rightE = e;
        //连接左右子树
        root -> left = construct(num,leftS,leftE);
        root -> right = construct(num,rightS,rightE);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        if(nums.size() == 0) return nullptr;
        return construct(nums,0,nums.size());
    }
};

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/579521.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存