トピック:
二分木は、木の前順および中次トラバーサルに従って構築されます。
注:
ツリーに重複する要素はないと想定できます。
たとえば、
Preorder traversal preorder = [3,9,20,15,7] Inorder
traversal inorder = [9,3,15,20,7]
は、次のバイナリツリーを返します。
3
/ \
9 20
/ \
15 7
分析方法:分割統治
「プレオーダートラバーサル」と「ミドルオーダートラバーサル」の定義を組み合わせる
プリオーダートラバーサルの最初のノードは、バイナリツリーのルートノードでなければなりません。
インオーダートラバーサルのルートノードは、インオーダートラバーサルを2つの部分に分割します。左側の部分はバイナリツリーのルートノードの左側のサブツリーを構成し、右側の部分はバイナリツリーのルートノードの右側のサブツリーを構成します。
ルートノードとして3を決定します。順序トラバーサルによれば、3は左側のルートノードの左側のサブツリーであり、右側のルートノードの右側のサブツリーであることがわかります。次に、再帰...
次に、アイデアを繰り返します
preLeftが前順トラバーサルの左境界であり、preRightが前順序トラバーサルの右境界であり、inLeftが中順序トラバーサルの左境界であり、inRightが中順序トラバーサルの右境界であるとします。
次に、preLeftはルートノードルートを指し、ルートノードの左側のサブツリーの左側の境界はpreLeft + 1です。同時に、ルートノードは中位のトラバーサルで見つけることができます。pIndexを中位のトラバースルートノードを指すように設定し、中位の順序がミドルルートノードの左の子をトラバースします。ツリーの間隔は[inLeft、pIndex-1]で、右側のサブツリーの間隔は[pIndex + 1、inRight]です。残っているのは、プリオーダが左サブツリーの右境界と右サブツリーの左境界をトラバースすることですが、左サブツリーの長さは、次の関係によって取得できる中次トラバースの長さと同じです。
最終的な結果は次のとおりです
コードを書く:
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public static TreeNode buildTree(int[] preorder, int[] inorder) {
int preLen = preorder.length;//前序遍历的长度
int inLen = inorder.length;//中序遍历的长度
// 可以不做判断,因为题目中给出的数据都是有效的
if (preLen != inLen) {
return null;
}
// 以空间换时间,否则,找根结点在中序遍历中的位置需要遍历
Map<Integer, Integer> map = new HashMap<>(inLen);
for (int i = 0; i < inLen; i++) {
map.put(inorder[i], i);
}
return buildTree(preorder,0, preLen - 1,map, 0, inLen - 1);
}
/**
* 根据前序遍历数组的 [preL, preR] 和 中序遍历数组的 [inL, inR] 重新组建二叉树
*
*
* @param preorder
* @param preL 前序遍历数组的区间左端点
* @param preR 前序遍历数组的区间右端点
* @param map
* @param inL 中序遍历数组的区间左端点
* @param inR 中序遍历数组的区间右端点
* @return 构建的新二叉树的根结点
*/
private static TreeNode buildTree(int[] preorder, int preL, int preR,
Map<Integer, Integer> map, int inL, int inR) {
if (preL > preR || inL > inR) {
return null;
}
// 构建的新二叉树的根结点一定是前序遍历数组的第 1 个元素
int rootVal = preorder[preL];
TreeNode root = new TreeNode(rootVal);
int pIndex = map.get(rootVal );//中序遍历根节点的索引
// 按照图中描述,计算边界的取值
root.left = buildTree(preorder, preL + 1, preL + (pIndex - inL), map, inL, pIndex - 1);
root.right = buildTree(preorder, preL + (pIndex - inL) + 1, preR, map, pIndex + 1, inR);
return root;
}
これで終わりです!
ソース:LeetCode
リンク:https ://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
著作権はLeetCode が所有しています。商用転載については、正式な許可書にご連絡ください。非商用転載については、出典を明記してください。