プレオーダーおよびインオーダーのトラバーサル シーケンスからバイナリ ツリーを構築する
2 つの整数配列 preorder と inorder が与えられた場合、preorder はバイナリ ツリーの事前順序トラバーサル、inorder は同じツリーの順序トラバーサルです。バイナリ ツリーを構築し、そのルート ノードを返します。
例 1:
入力: preorder = [3,9,20,15,7]、inorder = [9,3,15,20,7]
出力: [3,9,20,null,null,15,7]
まず第一に、
事前順序トラバーサルは、最初にルート ノードをトラバースし、次に左側のサブツリーをトラバースし、最後に右側のサブツリーをトラバースすることであることを理解する必要があります。順番
トラバーサルは、最初に左側のサブツリーをトラバースし、次にルート ノードをトラバースすることです。 、最後に右の
サブツリーを走査し、最初に左のサブツリーを走査し、次に右のサブツリーを走査し、最後にルート ノードを走査します。
まず、プリオーダーおよびインオーダーのトラバーサル シーケンスを使用してバイナリ ツリーを構築してみます。
プレオーダー トラバーサル シーケンス preorder とインオーダー トラバーサル シーケンス inorder を考えると、バイナリ
ツリーのプレオーダー トラバーサルは最初にルート ノードに到達する必要があることがわかります。そのため、プレオーダー シーケンスの最初の数字 3 がバイナリ ツリーのルート ノードであることがわかります。ツリー、および順序走査シーケンスでは、左のサブツリーは右のサブツリーの前に走査される必要があるため、順序走査シーケンス inorder はルート ノードを使用して順序を 3 つの区間に分割することがわかります。 (左のサブツリー) ルート (右)サブツリー)、ルート ノード 3 が左 要素は左側のサブツリー、3 の右側の要素は右側のサブツリーです。 ここで、3 の左側のサブツリーは空で、右側の
サブツリー (15、20、7) は引き続きバイナリツリーを構築するのと同じ方法
コード:
再帰呼び出しを使用して部分問題を分解する
class Solution {
public:
TreeNode* build(vector<int>& preorder,vector<int>& inorder,
int& prev,int inbegin,int inend)
{
//perorder 前序遍历序列,inorder 中序遍历序列,prev 指向前序遍历数列下标
if(inbegin>inend)return NULL;
//当前的根节点
TreeNode* root=new TreeNode(preorder[prev]);
int rooti=inbegin; //用来查找根节点在数组中的下班位置
while(rooti<inend)
{
if(inorder[rooti]==preorder[prev])break;
rooti++;
}
prev++; //每次使用完prev需往后走,prev指的是数组前序遍历中用来判断根节点的
//划分区间,(左子树,根)根(根,右子树)
// (inbegin,rooti-1)rooti(rooti+1,inend)
//函数递归继续构造二叉树的左右节点
root->left=build(preorder,inorder,prev,inbegin,rooti-1);
root->right=build(preorder,inorder,prev,rooti+1,inend);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int i=0;
TreeNode* root=build(preorder,inorder,i,0,inorder.size()-1);
return root;
}
};
順順および事後順のトラバーサル シーケンスからバイナリ ツリーを構築する
2 つの整数配列 inorder と postorder が与えられ、inorder はバイナリ ツリーのインオーダー トラバース、postorder は同じツリーのポストオーダー トラバースである場合、このバイナリ ツリーを構築して返してください。
例 1:
入力: inorder = [9,3,15,20,7]、postorder = [9,15,7,20,3]
出力: [3,9,20,null,null,15,7]
inorder および postorder トラバーサル シーケンスを使用してバイナリ ツリーを構築する場合、ルート preorder シーケンスと inorder シーケンスはバイナリ ツリーの構築に似ています。
バイナリ ツリーのインオーダー トラバース inorder とポストオーダー トラバースを考えると、
ルート ノードはバイナリ ツリーの後続のトラバースで最後にトラバースされることがわかります。そのため、ポストオーダー シーケンスの最後の要素 3 が、バイナリ ツリー。順序走査シーケンスでは、左側のサブツリー 最初にルートを走査し、ルートの後に右側のサブツリーを走査するよりも優れているため、これら 2 つの条件に従って、順序シーケンスを 3 つの区間に分割できます (左側のサブツリー)。ルート (右サブツリー)、ルート ノード 3 の左の要素は左サブツリー、3 の右の要素は右サブツリーです。3 の左
サブツリー シーケンスは 1 つだけあり、それが 3 の左ノードです。右側のサブツリー シーケンスにはまだ 3 つの要素があり、さらに分割して上記のプロセスを繰り返す必要があります。
コード:
class Solution {
public:
TreeNode* build(vector<int>& inorder, vector<int>& postorder,
int& prev,int inbegin,int inend)
{
if(inbegin>inend)return NULL;
TreeNode* root=new TreeNode(postorder[prev]);
int rooti=inbegin;
while(rooti<inend)
{
if(postorder[prev]==inorder[rooti])break;
rooti++;
}
prev--;
// (左,根)根(根,右)
//先构造右子树,再构造左子树
root->right=build(inorder,postorder,prev,rooti+1,inend);
root->left=build(inorder,postorder,prev,inbegin,rooti-1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
int i=postorder.size()-1;
TreeNode* root=build(inorder,postorder,i,0,postorder.size()-1);
return root;
}
};