トピックは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]です。
したがって、ルートノードを最初に作成し、次に、左ノードと右ノードを、事前順序、中間順序の左と右の配列に従って構成し、再帰を続けることができます...
細部
- いくつかの再帰後の事前順序では、順序付き配列が上下に対称的ではない場合があるため、それらのインデックスインデックスはpreIndex、inIndexに分割する必要があることに注意してください。
- マップストレージを使用してスピードアップ
コード
/**
* 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;
}