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

プレオーダーおよびインオーダーのトラバーサル シーケンスからバイナリ ツリーを構築する


トピックリンク

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;
    }
};

おすすめ

転載: blog.csdn.net/Tianzhenchuan/article/details/132085776