LintCode 73: Construct Binary Tree from Preorder and Inorder Traversal (二叉树经典题!)

本文介绍了一种算法,用于根据给定的先序和中序遍历序列构建二叉树。通过三种不同的实现方式,详细展示了如何定位根节点,划分左右子树,并递归构建完整的二叉树结构。
  1. Construct Binary Tree from Preorder and Inorder Traversal
    中文English
    Given preorder and inorder traversal of a tree, construct the binary tree.

Example
Example 1:

Input:[],[]
Output:{}
Explanation:
The binary tree is null
Example 2:

Input:[2,1,3],[1,2,3]
Output:{2,1,3}
Explanation:
The binary tree is as follows
2
/
1 3

Notice
You may assume that duplicates do not exist in the tree.

解法1:
代码如下:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     *@param preorder : A list of integers that preorder traversal of a tree
     *@param inorder : A list of integers that inorder traversal of a tree
     *@return : Root of a tree
     */
    TreeNode * buildTree(vector<int> &preorder, vector<int> &inorder) {
        return helper(preorder.begin(), preorder.end(), inorder.begin(), inorder.end());
    }
    
private:
    TreeNode * helper(vector<int>::iterator preorderStart, vector<int>::iterator preorderEnd,
                      vector<int>::iterator inorderStart, vector<int>::iterator inorderEnd) {
    if (inorderStart == inorderEnd) return NULL;
    
    vector<int>::iterator inorderRootIter = find(inorderStart, inorderEnd, *preorderStart);
    TreeNode * root = new TreeNode(*inorderRootIter);
    root->left = helper(preorderStart + 1, preorderStart + 1 + (inorderRootIter - inorderStart), inorderStart, inorderRootIter);
    root->right = helper(preorderStart + 1 + (inorderRootIter - inorderStart), preorderEnd, inorderRootIter + 1, inorderEnd);
    
    return root;
    }
    
};

二刷:

/**
 * 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int rootValue = preorder[0];
        TreeNode *root = new TreeNode(rootValue);
        int n = preorder.size();
        if (n == 1) return root;
        int inOrderRootIndex = 0;
        for (int i = 0; i < inorder.size(); i++) {
            if (inorder[i] == rootValue) {
                inOrderRootIndex = i;
                break;
            }
        }
        int leftChildNum = inOrderRootIndex, rightChildNum = n - leftChildNum - 1;
        
        if (leftChildNum > 0) {        
            vector<int> preorderLeft(preorder.begin() + 1, preorder.begin() + leftChildNum + 1);
            vector<int> inorderLeft(inorder.begin(), inorder.begin() + leftChildNum);
            root->left = buildTree(preorderLeft, inorderLeft);
        }
        if (rightChildNum > 0) {
            vector<int> preorderRight(preorder.begin() + leftChildNum + 1, preorder.end());
            vector<int> inorderRight(inorder.begin() + leftChildNum + 1, inorder.end());
            root->right = buildTree(preorderRight, inorderRight);
        }
        return root;
    }
};

三刷:可以先把inorder的num和index关系保存下来,这样就不用一个循环去找了。

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param preorder: A list of integers that preorder traversal of a tree
     * @param inorder: A list of integers that inorder traversal of a tree
     * @return: Root of a tree
     */
    TreeNode* buildTree(vector<int> &preorder, vector<int> &inorder) {
        int n1 = preorder.size(), n2 = inorder.size();
        if (n1 == 0 || n1 != n2) return NULL;
        for (int i = 0; i < n2; i++) um[inorder[i]] = i;
        return helper(preorder, 0, n1 - 1, inorder, 0, n2 - 1);
    }
private:
    unordered_map<int, int> um; //<num, inorder_index>
    TreeNode *helper(vector<int> &preorder, int start1, int end1, 
                     vector<int> &inorder, int start2, int end2) {
        if (start1 > end1) return NULL;
        TreeNode *root = new TreeNode(preorder[start1]);
    //    if (start1 == end1) return root; 这一行可以不要
        int pos = um[preorder[start1]];
        int leftSize = pos - start2;
        
        //root->left = helper(preorder, start1 + 1, start1 + pos, inorder, start2, start2 + pos - 1); //start2和pos不要搞混了!
        root->left = helper(preorder, start1 + 1, start1 + leftSize, inorder, start2, pos - 1); //这里要用leftSize, 不能直接用pos
        root->right = helper(preorder, start1 + leftSize + 1, end1, inorder, pos + 1, end2);
        return root;
    }
};
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值