首页 > 试题广场 >

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

[编程题]从中序与后序遍历序列构造二叉树
  • 热度指数:5470 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个二叉树的中序与后序遍历结果,请你根据两个序列构造符合这两个序列的二叉树。

数据范围:二叉树的节点数满足 ,节点上的值满足 ,保证节点的值各不相同

例如输入[2,1,4,3,5],[2,4,5,3,1]时,
根据中序遍历的结果[2,1,4,3,5]和后序遍历的结果[2,4,5,3,1]可构造出二叉树{1,2,3,#,#,4,5},如下图所示:

示例1

输入

[1],[1]

输出

{1}
示例2

输入

[2,1,4,3,5],[2,4,5,3,1]

输出

{1,2,3,#,#,4,5}

说明:本题目包含复杂数据结构TreeNode,点此查看相关信息
分治重构求解。中序遍历的顺序为:左中右;后序遍历的顺序为:左右中。因此后续遍历序列的最后一个元素为根节点,我们找到它在中序遍历中的位置,就可以把中序遍历序列划分为左右两部分,分别为左右子树的中序遍历序列;而根据中序遍历划分出来的左右子树的元素个数,我们又可以把后序遍历序列划分为左右两个部分。然后两个序列的左右部分分别走相同的过程进行递归重构,构建出根节点的左子树和右子树。
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param inorder int整型一维数组 中序遍历序列
     * @param postorder int整型一维数组 后序遍历序列
     * @return TreeNode类
     */
    public TreeNode buildTree (int[] inorder, int[] postorder) {
        // write code here
        if(inorder.length != postorder.length || inorder == null || inorder.length == 0) return null;
        int rootVal = postorder[postorder.length - 1];               // 后序遍历的最后一个元素是根节点
        TreeNode tree = new TreeNode(rootVal);                       // 构建根节点
        // 找到根节点在中序遍历中的位置
        int rootIndex = 0;
        for(int i = 0; i < inorder.length; i++){
            if(inorder[i] == rootVal){
                rootIndex = i;
                break;
            }
        }
        // 将序列划分为左右两个子树部分,分别进行重构
        tree.left = buildTree(Arrays.copyOfRange(inorder, 0, rootIndex), Arrays.copyOfRange(postorder, 0, rootIndex));
        tree.right = buildTree(Arrays.copyOfRange(inorder, rootIndex + 1, inorder.length), Arrays.copyOfRange(postorder, rootIndex, postorder.length - 1));
        return tree;
    }
}

发表于 2021-12-11 11:30:34 回复(0)
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param inorder int整型vector 中序遍历序列
     * @param postorder int整型vector 后序遍历序列
     * @return TreeNode类
     */
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // write code here
        if (postorder.empty()) return nullptr;
        TreeNode *root = new TreeNode(postorder[postorder.size() - 1]);
        vector<int> left, right;
        for (int i = 0; i < inorder.size(); ++i) {
            if (inorder[i] == root->val) {
                // left
                vector<int> left_in(inorder.begin(), inorder.begin() + i);
                vector<int> left_post(postorder.begin(), postorder.begin() + i);
                root->left = buildTree(left_in, left_post);
                // right
                vector<int> right_in(inorder.begin() + i + 1, inorder.end());
                vector<int> right_post(postorder.begin() + i, postorder.end() - 1);
                root->right = buildTree(right_in, right_post);
            }
        }
        return root;
    }
};

发表于 2022-07-19 17:48:50 回复(0)
简介优雅,这才是好代码。
int post_idx;

TreeNode* build(int i1, int i2, vector<int>& inorder, vector<int>& postorder){
    if(i1 > i2)
        return nullptr;
    vector<int>::iterator it = find(inorder.begin() + i1, inorder.begin() + i2 + 1, postorder[post_idx]);
    int idx = distance(inorder.begin(), it);
    TreeNode *newNode = new TreeNode(inorder[idx]);
    post_idx --;
    newNode->right = build(idx +1, i2, inorder, postorder);
    newNode->left = build(i1, idx - 1, inorder, postorder);
    return newNode;
}

TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
    post_idx = postorder.size() - 1;
    return build(0, inorder.size() - 1, inorder, postorder);
}


发表于 2023-03-21 23:05:20 回复(0)
package main
//import "fmt"
import . "nc_tools"
/*
 * type TreeNode struct {
 *   Val int
 *   Left *TreeNode
 *   Right *TreeNode
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param inorder int整型一维数组 中序遍历序列
 * @param postorder int整型一维数组 后序遍历序列
 * @return TreeNode类
*/
func buildTree( inorder []int ,  postorder []int ) *TreeNode {
    // write code here
    if len(postorder) == 0{
        return nil
    }
    newNode := new(TreeNode)
    newNode.Val = postorder[len(postorder) - 1]
    for i := 0; i < len(inorder); i++{
        if newNode.Val == inorder[i]{
            newNode.Left = buildTree(inorder[:i], postorder[:i])
            newNode.Right = buildTree(inorder[i+1:], postorder[i:len(postorder)-1])
            return newNode
        }
    }
    return newNode
}

发表于 2024-04-11 22:09:09 回复(0)
不改动参数的递归解法
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // write code here
        if(inorder.size()==0||postorder.size()==0) return nullptr;
        int x=*postorder.rbegin();
        TreeNode *root=new TreeNode(x);
        int post;
        for(int i=0;i<inorder.size();i++)
        {
            if(inorder[i]==x) post=i;
        }
        vector<int> lin;
        vector<int> rin;
        for(int i=0;i<post;i++) lin.push_back(inorder[i]);
        for(int i=post+1;i<inorder.size();i++) rin.push_back(inorder[i]);
        vector<int>lpost;
        vector<int>rpost;
        for(int i=0;i<post;i++)lpost.push_back(postorder[i]);
        for(int i=post;i<postorder.size()-1;i++)rpost.push_back(postorder[i]);
        root->left=buildTree(lin, lpost);
        root->right=buildTree(rin, rpost);
        return root;
    }

编辑于 2024-03-23 19:20:29 回复(0)
c语言
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */

#include <stdlib.h>
void build_root(struct TreeNode** root,int* inorder,int left1,int right1,int* postorder, int* idx){
    if(left1 > right1 || *idx == -1){
        return;
    }
    *root = malloc(sizeof(struct TreeNode));
    printf("%d ",postorder[*idx]);
    (*root)->val = postorder[*idx];
    (*idx)--;
    (*root)->left = NULL;
    (*root)->right = NULL;
    //找到postOrder[*idx]在inorder的位置
    for(int i = left1; i <= right1;i++){
        if(inorder[i] == (*root)->val){ //找到
            //判断*idx 是否已经走完
            if(*idx != -1){
                //判断下一个根节点的位置是在inorder[i]的左边还是右边
                int flag = 1;//1右边,0左边
                for(int j = left1; j <= i;j++){
                    if(inorder[i] ==postorder[*idx]){
                        //在左边
                        flag = 0;
                        break;
                    }
                }
                if(flag == 0){
                    build_root(&((*root)->left), inorder, left1, i-1,postorder, idx);
                    build_root(&((*root)->right), inorder, i+1, right1,postorder, idx);
                } else {
                    build_root(&((*root)->right), inorder, i+1, right1,postorder, idx);
                    build_root(&((*root)->left), inorder, left1, i-1,postorder, idx);
                }    
            }
            break;
        }
    }
}

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param inorder int整型一维数组 中序遍历序列
 * @param inorderLen int inorder数组长度
 * @param postorder int整型一维数组 后序遍历序列
 * @param postorderLen int postorder数组长度
 * @return TreeNode类
 */
struct TreeNode* buildTree(int* inorder, int inorderLen, int* postorder, int postorderLen ) {
    // write code here
    //记录节点数为1000个,记录输入值中
    struct TreeNode* root;
    int idx = postorderLen-1;
    build_root(&root, inorder, 0, inorderLen - 1, postorder,&idx);
    return root;

}


编辑于 2024-02-18 17:54:23 回复(0)
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param inorder int整型一维数组 中序遍历序列
     * @param postorder int整型一维数组 后序遍历序列
     * @return TreeNode类
     */
    public TreeNode buildTree (int[] inorder, int[] postorder) {
        // write code here
        return build(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
    }
    // 左 中 右
    // 左 右 中
    private TreeNode build(int[] inOrder, int li, int ri, int[] postorder, int lp, int rp) {
        if(li > ri) return null;
        TreeNode cur = new TreeNode(postorder[rp]);
        int i = li;
        for(; i <= ri; i++) {
            if(inOrder[i] == postorder[rp]) break;
        }
        cur.left = build(inOrder, li, i - 1,  postorder, lp, lp + i  - li - 1);
        // ri - i - 1
        cur.right = build(inOrder, i + 1, ri, postorder, rp - ri + i, rp - 1);
        return cur;

    }
}

发表于 2024-02-06 02:11:27 回复(0)
C语言代码实现:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
};

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param inorder int整型一维数组 中序遍历序列
 * @param inorderLen int inorder数组长度
 * @param postorder int整型一维数组 后序遍历序列
 * @param postorderLen int postorder数组长度
 * @return TreeNode类
 */
struct TreeNode* buildTree(int* inorder, int inorderLen, int* postorder, int postorderLen ) {
	// write code here
	if (inorderLen < 1 || postorderLen < 1)return NULL;
	struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
	root->val = postorder[postorderLen - 1];
	int* p = inorder;
	for (; p < inorder + inorderLen; p++) {
		if (*p == postorder[postorderLen - 1])
			break;
	}
	int k = p - inorder;	//左子树结点数量
	//递归构建左子树:中序开始位置inorder,后序开始位置postorder
	root->left = buildTree(inorder, k, postorder, k);

	//右子树结点数量inorderLen - k - 1
	//递归构建右子树:中序开始位置p+1,后序开始位置postorder+k
	root->right = buildTree(p + 1, inorderLen - k - 1, postorder + k, inorderLen - k - 1);
	return root;
}

//前序遍历
void preOrder(struct TreeNode* root) {
	if (root) {
		printf("%d ", root->val);
		preOrder(root->left);
		preOrder(root->right);
	}
}

int main(int argc, char *argv[])
{
	int inorder[] =   {2, 1, 4, 3, 5};
	int postorder[] = {2, 4, 5, 3, 1};
	int n = sizeof(inorder) / sizeof(int);
	struct TreeNode* root = buildTree(inorder, n, postorder, n);
	preOrder(root);
	printf("\n");

	return 0;
}


发表于 2023-10-15 18:53:49 回复(0)
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode* left;
 *	struct TreeNode* right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
    int post_idx;  // 从后序遍历的 最后一个元素开始
    unordered_map<int, int> idx_map;// 建立(中序元素,后序下标)键值对的哈希表
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // 从后序遍历的最后一个元素开始
        post_idx = (int)postorder.size()-1;
        int idx = 0;  // 建立(中序元素,中序下标)键值对的哈希表
        for (auto& val : inorder) 
            idx_map[val] = idx++;
        return helper(0, (int)inorder.size()-1, inorder, postorder);
    }
    TreeNode* helper(int in_left, int in_right, vector<int>& inorder, vector<int>& postorder){  
        if (in_left > in_right) // 如果这里没有节点构造二叉树了,就结束
            return nullptr;
        int root_val = postorder[post_idx]; //1 选择post_idx位置的元素,作为当前子树 根节点
        post_idx--; // 下标减一 
        TreeNode* root = new TreeNode(root_val); // 根节点

        int index = idx_map[root_val];      //2 根据root所在中序的index,将中序分成左右两棵子树

        root->right = helper(index+1, in_right,  inorder, postorder); // 1构造root节点的右子树
        root->left  = helper(in_left,   index-1, inorder, postorder); // 2构造root节点的左子树
        return root; // 根节点
    }
};


发表于 2023-09-24 17:02:41 回复(0)
划分左右子叶的思想解题。
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
#include <unordered_map>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param inorder int整型vector 中序遍历序列
     * @param postorder int整型vector 后序遍历序列
     * @return TreeNode类
     */
    TreeNode* buildTreehelper(vector<int>& inorder, int instart, int inend, vector<int>& postorder, int poststart, int postend, unordered_map<int, int>& map){
        if(instart > inend || poststart > postend){
            return nullptr;  // 递归终止条件
        }
        // 在后续数组中找根节点
        TreeNode* root = new TreeNode(postorder[postend]);
        int rootIndex = map[postorder[postend]];
        // 根据中序数组分割左右子树
        // 中序数组中的左片段[instart, rootIndex - 1]  ***
        // 中序数组中的右片段[rootIndex + 1, inend]
        // 后续数组中的左片段[poststart, poststart + (rootIndex - instart) - 1]  ***
        // 后续数组中的右片段[poststart + (rootIndex - instart), postend - 1]
        root->left = buildTreehelper(inorder, instart, rootIndex - 1, postorder, poststart, poststart + (rootIndex - instart) - 1, map);
        root->right = buildTreehelper(inorder, rootIndex + 1, inend, postorder, poststart + (rootIndex - instart), postend - 1, map);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // 先把中序数组的位置用哈希表存起来,方便查找
        unordered_map<int, int> map;
        for(int i = 0; i < inorder.size(); i++){
            map[inorder[i]] = i;
        }
        return buildTreehelper(inorder, 0, inorder.size()-1, postorder, 0, postorder.size()-1, map);
    }
};


发表于 2023-07-26 12:06:26 回复(0)
class Solution:
    def buildTree(self , inorder: List[int], postorder: List[int]) -> TreeNode:
        def build(pos_left, pos_right, mid_left, mid_right):
            if pos_left > pos_right or mid_left > mid_right:  # 停止条件
                return None
            root = TreeNode(postorder[pos_right])  # 构建节点
            mid_root = mid_left
            while mid_root <= mid_right and inorder[mid_root] != postorder[pos_right]:  #找寻根节点
                mid_root += 1
            diff = mid_root - mid_left  # 左子树的长度
            root.left = build(pos_left, pos_left + diff -1, mid_left, mid_root - 1)  # 构建左子树
            root.right = build(pos_left + diff, pos_right - 1, mid_root + 1, mid_right)  # 构建右子树
            return root  # 返回构建好的树

        return build(0, len(postorder) - 1, 0, len(inorder) - 1)

发表于 2023-07-21 12:59:02 回复(0)
/*
 * function TreeNode(x) {
 *   this.val = x;
 *   this.left = null;
 *   this.right = null;
 * }
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param inorder int整型一维数组 中序遍历序列
 * @param postorder int整型一维数组 后序遍历序列
 * @return TreeNode类
 */
function buildTree( inorder ,  postorder ) {
    if(postorder.length==0) return null;
    let root_val=postorder[postorder.length-1];
    let idx=inorder.indexOf(root_val);
    let root=new TreeNode(root_val);
    root.left=buildTree(inorder.slice(0,idx),postorder.slice(0,idx));
    root.right=buildTree(inorder.slice(idx+1),postorder.slice(idx,postorder.length-1));
    return root;
}
module.exports = {
    buildTree : buildTree
};

发表于 2022-11-15 14:06:08 回复(0)
Map<Integer, Integer> inOrderMap;
int[] postOrder;
int postIdx;

public TreeNode buildTree(int[] inorder, int[] postorder) {
    // 将中序下标放入Map中
    Map<Integer, Integer> inOrderMap = new HashMap<>();
    for (int i=0; i<inorder.length; i++) {
        inOrderMap.put(inorder[i], i);
    }
    this.inOrderMap = inOrderMap;
    this.postIdx = postorder.length-1;
    this.postOrder = postorder;
    return build(0, inorder.length-1);
}

public TreeNode build(int leftIdx, int rightIdx) {
    if (leftIdx > rightIdx) {
        return null;
    }
    int rootVal = postOrder[postIdx--];
    int rootIdx = inOrderMap.get(rootVal);
    TreeNode root = new TreeNode(rootVal);
    // 通过后序遍历往前推,所以先处理右子树
    // 中序遍历,root点的右边是右子树,左边是左子树
    root.right = build(rootIdx+1, rightIdx);
    root.left = build(leftIdx, rootIdx-1);
    return root;
}

发表于 2022-09-24 11:12:14 回复(0)
1:后序最后一个必然为根节点
2:根据根节点划分左节点的中序和后序分部分与右节点的中序和后序部分,然后将左右节点对应的中序和后序作为函数递归的参数
/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 *  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
  public:
    int GetIdxFromInOrder(vector<int>& inorder, int val) {
        // 只要inorder不为空,必然存在有效索引
        for (int  i = 0; i < inorder.size(); i++) {
            if (inorder[i] == val) {
                return i;
            }
        }
        return -1;
    }

    TreeNode* BuildNode(vector<int>& inorder, vector<int>& postorder) {
        if (postorder.empty()) {
            return nullptr;
        }
        int rootVal = postorder[postorder.size() - 1];
        TreeNode* root = new TreeNode(rootVal);
        if (postorder.size() == 1) {
            // 只有根节点
            return root;
        }
        int idx = GetIdxFromInOrder(inorder, rootVal);
        if (idx < 0) {
            // 只有
            return root;
        }
        // 使用左节点的中序和后序计算左节点
        vector<int> midIn(inorder.begin(), inorder.begin() + idx);
        vector<int> midPost(postorder.begin(), postorder.begin() + midIn.size());
        root->left = BuildNode(midIn, midPost);
        // 使用右节点的中序和后序计算右节点
        vector<int> postIn(inorder.begin() + idx + 1, inorder.end());
        vector<int> postPost(postorder.begin() + midIn.size(), postorder.end() - 1);
        root->right = BuildNode(postIn, postPost);
        return root;
    }
    // 后序的最后一个节点为根节点;中序被根节点分为左右子节点
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // write code here
        if (postorder.size() == 0) {
            return nullptr;
        }

        TreeNode* root = BuildNode(inorder, postorder);
        return root;
    }
};
发表于 2022-08-28 20:59:50 回复(0)
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#

# @param inorder int整型一维数组 中序遍历序列
# @param postorder int整型一维数组 后序遍历序列
# @return TreeNode类
#
class Solution:
    def buildTree(self , inorder: List[int], postorder: List[int]) -> TreeNode:
        # write code here
        n = len(postorder)
        m = len(inorder)
        # 要求中序和后续都不能为空
        if m == 0 or n == 0:
            return None
        # 先找到根节点
        root = TreeNode(postorder[-1])
        for i in range(len(inorder)):
            # 找到中序遍历的第一个根节点
            if inorder[i] == postorder[-1]:
                # 左子树的后续遍历
                leftpos = postorder[:i]
                # 左子树的中序遍历
                leftvin = inorder[:i]
                # 重构左子树
                root.left = self.buildTree(leftvin, leftpos)
                # 右子树的后续遍历
                rightpos = postorder[i:-1]
                # 右子树的中序遍历
                rightvin = inorder[i+1:]
                # 重构右子树
                root.right = self.buildTree(rightvin, rightpos)
                break
        return root
发表于 2022-06-10 19:33:27 回复(0)
typedef struct TreeNode TreeNode;
TreeNode* tree(int* inorder, int inL,int inR, int* postorder, int postL,int postR);

struct TreeNode* buildTree(int* inorder, int inorderLen, int* postorder, int postorderLen ) {
    // write code here
    return tree(inorder,0,inorderLen-1,postorder,0,postorderLen-1);
    
}

//递归法构造
TreeNode* tree(int* inorder, int inL,int inR, int* postorder, int postL,int postR)
{
    if(postL>postR)
        return NULL;
    
    TreeNode* node = malloc(sizeof(TreeNode));
    node->val=postorder[postR];
    int pos = inL;
    while(pos<=inR && inorder[pos]!=node->val)
    {
        ++pos;
    }
    node->left = tree(inorder, inL, pos-1, postorder, postL, postL+pos-inL-1);
    node->right = tree(inorder, pos+1, inR, postorder, postL+pos-inL, postR-1);
    return node;
}

发表于 2022-03-17 20:54:54 回复(0)
 1.用哈希表存储中序的值和索引(可以使用for循环的方式来找寻根节点在中序的索引),索引用于左右子树的划分
 2.构建划分函数
    1.递归出口,左大于右结束。
    2.根节点值为后序的最后一个节点并在中序遍历中找到这个值(将他左右划分,左边为左子树,右边为右子树)
    3.创建节点。值为上述找出的值
    4.递归的划分左右子树,并返回创建的节点,不一定是最终的根节点
3.返回根节点
    int[] post;
    HashMap<Integer,Integer> inorderMap = new HashMap<Integer,Integer>();
    public TreeNode buildTree (int[] inorder, int[] postorder) {
       for(int i = 0;i<inorder.length;i++){
           inorderMap.put(inorder[i],i);
       }
        // write code here
        post = postorder;
        int len = inorder.length;
        
        return build(0,len - 1,0,len -1);
    }
    private TreeNode build(int inleft,int inright,int postleft,int postright){
        if(inleft > inright || postleft > postright){
            return null;
        }
        int value = post[postright];
        int index = inorderMap.get(value);
        TreeNode root = new TreeNode(value);
        root.left = build(inleft,index - 1,postleft,postleft+index-inleft -1);
        root.right = build(index+1,inright,postleft+index-inleft,postright -1);
        return root;
    }

发表于 2022-02-22 12:38:16 回复(0)

思路:

1.中序遍历顺序:左根右;后序遍历顺序:左右根;根据给出的后序遍历数组可知,数组末元素为根结点值;取出该结点,作为根结点的值。

2.根据中序遍历顺序,找出根结点位置rootIdx;在中序遍历数组中,该结点左边元素为左子树结点值,右边为右子树结点值;在后序遍历数组中,可知从0到rootIdx为左子树结点,从rootIdx到倒数第二个元素为右子数结点。

3.根据中序遍历左子数,后序遍历左子数数组初始化左子树,作为根结点的左子树;根据中序遍历右子数,后序遍历右子数数组初始化右子树,作为根结点的右子树;

4.返回根结点



import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param inorder int整型一维数组 中序遍历序列
     * @param postorder int整型一维数组 后序遍历序列
     * @return TreeNode类
     */
    public TreeNode buildTree (int[] midorder, int[] postorder) {
        // write code here
        //用递归的方式,从上向下逐渐构建二叉树
        //无结点
        if(midorder.length==0 || midorder==null || midorder.length!=postorder.length)
            return null;
        else if(midorder.length==1 && midorder.length==postorder.length){  //1个节点
            TreeNode root = new TreeNode(midorder[0]);
            root.left=null;
            root.right=null;
            return root;
        }
        //多个节点
        int len = midorder.length;
        int val = postorder[len-1];
        TreeNode root = new TreeNode(val);
        int index=0;  //根节点,用于记录其在中序遍历中的索引值
        for(int i=0;i<len;i++){
            if(val==midorder[i])
                index = i;
        }
        root.left = buildTree( Arrays.copyOfRange(midorder,0,index), Arrays.copyOfRange(postorder,0,index) );
        root.right = buildTree(Arrays.copyOfRange(midorder,index+1,len), Arrays.copyOfRange(postorder,index,len-1) );
        return root;
    }
}
发表于 2022-02-22 11:24:51 回复(0)
class Solution:
    def buildTree(self , inorder: List[int], postorder: List[int]) -> TreeNode:
        # write code here
        if postorder:
            ind=inorder.index(postorder[-1])
            root=TreeNode(postorder.pop())
            root.left=self.buildTree(inorder[:ind],postorder[:ind])#左都同
            root.right=self.buildTree(inorder[ind+1:],postorder[ind:])
            return root

发表于 2022-01-22 07:13:42 回复(0)
// 先构造根节点再递归左右子树,关键在help辅助函数的下标如何写
public class Solution {
    public TreeNode buildTree (int[] inorder, int[] postorder) {
        for (int i = 0; i < inorder.length; i++)
            map.put(inorder[i], i);
        return help(inorder, 0, inorder.length-1, postorder, 0, postorder.length-1);
    }
    public Map<Integer, Integer> map = new HashMap<>();
    public TreeNode help(int[] inorder, int inStart, int inEnd,
                         int[] postorder, int postStart, int postEnd) {
        if (inStart > inEnd) return null;
        int idx = map.get(postorder[postEnd]);
        int l = idx - inStart;
        TreeNode root = new TreeNode(postorder[postEnd]);
        root.left = help(inorder, inStart, idx-1,
                         postorder, postStart, postStart+l-1);
        root.right = help(inorder, idx+1, inEnd,
                          postorder, postStart+l, postEnd-1);
        return root;
    }
}
发表于 2022-01-04 16:30:41 回复(1)