LeetCodeブラッシングノート_105。プレオーダーおよびミドルオーダーのトラバーサルシーケンスからバイナリツリーを作成します。

トピックはLeetCodeからです

105.プレオーダーおよびミドルオーダーのトラバーサルシーケンスからバイナリツリーを構築します。

他のソリューションまたはソースコードにアクセスできます:tongji4m3

解説

二分木は、木の前順および中次トラバーサルに従って構築されます。

注:
ツリーに重複する要素はないと想定できます。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

アイデア

プレオーダーとミドルオーダーでトラバースされた配列[lo、hi]の場合:

  • プレオーダーのルートノードはloで、ミドルオーダーのルートノードはiです。
  • プレオーダーの左側のサブツリーは[lo + 1、i]、右側のサブツリーは[i + 1、hi]です。
  • 中位の左側のサブツリーは[lo、i-1]で、右側のサブツリーは[i + 1、hi]です。

したがって、ルートノードを最初に作成し、次に、左ノードと右ノードを、事前順序、中間順序の左と右の配列に従って構成し、再帰を続けることができます...

細部

  1. いくつかの再帰後の事前順序では、順序付き配列が上下に対称的ではない場合があるため、それらのインデックスインデックスはpreIndex、inIndexに分割する必要があることに注意してください。
  2. マップストレージを使用してスピードアップ

コード

/**
 * look 用map存储加快速度
树中没有重复元素
用map存储inorder数组的值和对应索引
 方便找到根节点位置
 */
private Map<Integer, Integer> map = new HashMap<>();

public TreeNode buildTree(int[] preorder, int[] inorder)
{
    
    
    for (int i = 0; i < inorder.length; i++)
    {
    
    
        map.put(inorder[i], i);
    }
    return buildTree(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}

private TreeNode buildTree(int[] preorder, int preLo, int preHi, int[] inorder, int inLo, int inHi)
{
    
    
    if (preLo > preHi || inLo > inHi)
    {
    
    
        return null;
    }
    //找到根节点在中序遍历的索引位置
    int inIndex = map.get(preorder[preLo]);
    //look,i在经过几次之后,只是对应了inorder的i,但是对于preorder,应该只是一个偏移量
    //inIndex - inLo代表左子树的个数,preIndex则是前序遍历左子树的最后一个元素
    int preIndex = preLo + inIndex - inLo;
    TreeNode root = new TreeNode(preorder[preLo]);
    root.left = buildTree(preorder, preLo + 1, preIndex, inorder, inLo, inIndex - 1);
    root.right = buildTree(preorder, preIndex + 1, preHi, inorder, inIndex + 1, inHi);
    return root;
}

おすすめ

転載: blog.csdn.net/weixin_42249196/article/details/108545206