LintCode 72: Construct Binary Tree from Inorder and Postorder Traversal (二叉树重建经典题)

本文介绍了一种算法,该算法利用给定的中序和后序遍历序列来构建二叉树。通过解析后序遍历的最后一个元素作为根节点,并在中序遍历中定位该节点,可以递归地构建左子树和右子树。文章提供了详细的C++代码实现,包括使用映射优化查找过程的方法。

72. Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree.

Example

Example 1:

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

Example 2:

Input:[1,2,3],[1,3,2]
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.

Input test data (one parameter per line)How to understand a testcase?

解法1:
根据postOrder的最后一个节点为根节点找到其在inOrder中的位置,然后就可以找出左子树的节点范围和右子树的节点范围进行递归。

注意:
1) 在对右子树递归时,需要减去最后一个节点即根节点。

root->right = helper(inorder, rootIndex + 1, inEnd, postorder, postEnd - rightTreeCount, postEnd - 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 inorder: A list of integers that inorder traversal of a tree
     * @param postorder: A list of integers that postorder traversal of a tree
     * @return: Root of a tree
     */
    TreeNode * buildTree(vector<int> &inorder, vector<int> &postorder) {
        return helper(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
    }
private:
    TreeNode * helper(vector<int> &inorder, int inStart, int inEnd, vector<int> &postorder, int postStart, int postEnd) {
        if (inStart > inEnd || inEnd < 0 || postEnd < 0) {
            return NULL;
        }
        
        TreeNode * root = new TreeNode(postorder[postEnd]);
        int rootIndex = 0;
        
        for (int i = inStart; i <= inEnd; ++i) {
            if (inorder[i] == postorder[postEnd]) {
                rootIndex = i;
                break;
            }
        }
        int leftTreeCount = rootIndex - inStart;
        int rightTreeCount = inEnd - rootIndex;
        root->left = helper(inorder, inStart, rootIndex - 1, postorder, postStart, postStart + leftTreeCount - 1);
        root->right = helper(inorder, rootIndex + 1, inEnd, postorder, postEnd - rightTreeCount, postEnd - 1);
        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>& inorder, vector<int>& postorder) {
        return helper(inorder, 0, inorder.size() - 1, postorder, 0, postorder.size() - 1);
    }
private:
    TreeNode* helper(vector<int>& inorder, int inStart, int inEnd, vector<int>& postorder, int postStart, int postEnd) {
        if (inStart > inEnd || postStart > postEnd) return NULL;
        int rootValue = postorder[postEnd];
        TreeNode *root = new TreeNode(rootValue);
        if (inStart == inEnd || postStart == postEnd) return root;
        int rootIndex = inStart;
        
        for (int i = inStart; i <= inEnd; i++) {
            if (inorder[i] == rootValue) {
                rootIndex = i;
                break;
            }
        }
        int leftNodeNum = rootIndex - inStart, rightNodeNum = inEnd - rootIndex;
  
      //  cout << "leftNodeNum=" << leftNodeNum << " rightNodeNum=" << rightNodeNum << endl;
        if (leftNodeNum > 0) {
            root->left = helper(inorder, inStart, rootIndex - 1, postorder, postStart, postStart + leftNodeNum - 1);
        }
        if (rightNodeNum > 0) {
            root->right = helper(inorder, rootIndex + 1, inEnd, postorder, postStart + leftNodeNum, postEnd - 1);
        }
        return root;
    }
};

三刷:用一个map把inorder的num和index保存下来,用来得到leftSize。




class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        int n = inorder.size(), n2 = postorder.size();
        if (n == 0 || n != n2) return NULL;
        for (int i = 0; i < n; i++) um[inorder[i]] = i;
        return helper(inorder, 0, n - 1, postorder, 0, n - 1);
    }
private:
    unordered_map<int, int> um; //<num, index in inodrder>
    TreeNode *helper(vector<int>& inorder, int start1, int end1, vector<int>& postorder, int start2, int end2) {
        if (start1 > end1) return NULL;
    //    if (start1 == end1) return new TreeNode(inorder[start1]);
        int pos = um[postorder[end2]];
        int leftSize = pos - start1;
        TreeNode *root = new TreeNode(postorder[end2]);
        root->left = helper(inorder, start1, pos - 1, postorder, start2, start2 + leftSize - 1);
        root->right = helper(inorder, pos + 1, end1, postorder, start2 + leftSize, end2 - 1);
        return root;
    }
};

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值