zoukankan      html  css  js  c++  java
  • 《剑指offer》重建二叉树

    本题来自《剑指offer》 重构二叉树

    题目:

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

    思路:

      二叉树的前序遍历:根左右,第一个值是根节点

      二叉树的中序遍历:左根右,根节点的值在中间,左子树的节点在根的左边,右子树的节点在根的右边

      首先找到前序的根节点,继而对应到中序中,分离出中序的根左、右子树。

      其次对中序的左右子树,对应的找到前序的左右子树。

      左、右子树同样是数,所以采用递归的思路进行遍历。

      终止条件,当前序只有一个值时候,便是根节点,当没有值就返回None。

    C++ Code:(未调通,栈溢出,是边界条件没有调好,后期改)

    /**
     * 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) {
            if (pre.size() == 0){                                        //当前序为空时候,返回为空
                return NULL;
            }else if(pre.size() == 1){                                  //当只有一个元素时候,便直接是根节点
                TreeNode* root = new TreeNode(pre[0]);
                return root;
            }else{
                std::vector<int> vin_left,vin_right,pre_left,pre_right; //定义前序和中序的左右子节点
                for (int i = 0;vin[i]!=pre[0];i++){                     //中序的左节点
                    vin_left.push_back(vin[i++]);
                }
                for (int i = vin_left.size()+1;i<vin.size();i++){        //中序的右子节点
                    vin_right.push_back(vin[i]);
                }
                for (int i = 1;i<vin_left.size();i++){                   //前序的左子节点
                    pre_left.push_back(pre[i]);
                }
                for (int i = pre_left.size()+1;i<pre.size();i++){        //前序的右子节点
                    pre_right.push_back(pre[i]);
                }
                TreeNode* root = new TreeNode(pre[0]);                   //构造根节点,其值就是前序的第一个值
                root->left = reConstructBinaryTree(pre_left,vin_left);   //左节点是递归的调用,前左子节点和中左子节点
                root->right = reConstructBinaryTree(pre_right,vin_right);//右节点是递归的调用,前右子节点和中右子节点
                return root;                                             //将其返回
            }
            
        }
    };

    Python Code:

    # -*- coding:utf-8 -*-
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    class Solution:
        # 返回构造的TreeNode根节点
        def reConstructBinaryTree(self, pre, tin):
            # write code here
            if len(pre) == 0:                             #当数据中没有数据返回None
                return None
            elif len(pre) == 1:                           #当前序中只有一个数时,则为根节点,直接返回
                return TreeNode(pre[0])
            else:
                tin_left = tin[:tin.index(pre[0])]        #中序的左子树为从头到前序的根节点
                tin_right = tin[tin.index(pre[0])+1:]     #中序的右子树为从根节点到尾部全部
                pre_left = pre[1:len(tin_left)+1]         #前序的左子树为从根节点开始到中序的左子树
                pre_right = pre[len(tin_left)+1:]         #前序的右子树为中序的右子树
                res = TreeNode(pre[0])                    #定义根节点
                res.left = Solution.reConstructBinaryTree(self,pre_left,tin_left)   #递归的调用左子树
                res.right = Solution.reConstructBinaryTree(self,pre_right,tin_right)#递归的调用右子树
                return res                                #最终返回根节点

    # -*- coding: utf-8 -*-
    """
    Created on Mon Apr  8 14:18:46 2019
    
    @author: Administrator
    输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
    假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
    例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
    
    思路:
    前序的第一个为根节点,依次找到其左节点的放在一起,右节点的放在一起,递归计算
    """
    
    class TreeNode:
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    class Solution:
        # 返回构造的TreeNode根节点
        def reConstructBinaryTree(self, pre, tin):
            # write code her
            if len(pre) == 0:   #如果没有节点就直接返回None
                return None
            elif len(pre) == 1: #如果只有一个节点就直接是头结点了,直接返回
                return TreeNode(pre[0])
            else: 
                tin_left = tin[:tin.index(pre[0])]  #截取中左区域
                tin_right = tin[tin.index(pre[0])+1:]   #截取中右区域
                pre_left = pre[1:len(tin_left)+1]   #截取前左区域
                pre_right = pre[len(tin_left)+1:]   #截取前右区域
                res = TreeNode(pre[0])  #头结点为前的第0个节点
                res.left = Solution.reConstructBinaryTree(self,pre_left,tin_left)   #递归,左节点是前左和中左
                res.right = Solution.reConstructBinaryTree(self,pre_right,tin_right)#递归,右节点是前右和中右
                return res
        #前序遍历
        def preorder(self,node):
            if node:
                print(node.val)
                Solution.preorder(self,node.left)
                Solution.preorder(self,node.right)
        # 中序遍历
        def inorder(self,node):
            if node:
                Solution.inorder(self,node.left)
                print(node.val)
                Solution.inorder(self,node.right)
        #后序遍历
        def postorder(self,node):
            if node:
                Solution.postorder(self,node.left)
                Solution.postorder(self,node.right)
                print(node.val)
    if __name__ == '__main__':
        pre = [1,2,4,7,3,5,6,8]
        tin = [4,7,2,1,5,3,8,6]
        solution = Solution()
        tree = solution.reConstructBinaryTree(pre,tin)
        solution.preorder(tree)

    总结:

      发现规律,终止和其实条件。

  • 相关阅读:
    Confluence 6 连接一个目录
    卸载 PrestaShop 1.7
    一“脚”到位-淋漓尽致的自动化部署
    从细节处谈Android冷启动优化
    视觉设计师的进化
    网易对象存储NOS图床神器
    移动端互动直播(入门篇)
    SpringBoot入门(五)——自定义配置
    SpringBoot入门(四)——自动配置
    SpringBoot入门(三)——入口类解析
  • 原文地址:https://www.cnblogs.com/missidiot/p/10757106.html
Copyright © 2011-2022 走看看