LeetCode [105/106/112] プレオーダーおよびインオーダー トラバーサル シーケンスからバイナリ ツリーを構築、インオーダーおよびポストオーダー トラバーサル シーケンスからバイナリ ツリーを構築、パス合計 C/C++——第 2 週 III

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

タイトル説明[中]:

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]
1

アイデア [再帰]:

例 1 のツリーを見ると、事前順序走査シーケンスは [3,9,20,15,7]、順序走査シーケンスは [9,3,15,20,7] であることがわかります
。ルート ノードは 3、左側のサブツリーの順序トラバーサルは [9]、右側のサブツリーの順序トラバーサルは [15, 20, 7] であることがわかります。事前順序トラバーサルにより、左側のサブツリーの事前順序トラバーサルは [9] 、右側のサブツリーの事前順序トラバーサルは [20、15、7] です。次に、左右のサブツリーを事前順序および順序で再帰的に走査することによって、バイナリ ツリーの構築を実現できます。
注: 各再帰の後、順序シーケンス内の現在のルート ノードの添え字を見つける必要があります。効率を向上させるために、ハッシュ テーブルを構築して、順序シーケンス内のすべてのノードの位置を保存できます。このようにして、探索時間をO(n)→O(1)と変化させることができる。

C++ コード:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    
    
    //定义一个哈希表
    unordered_map<int, int> pos;

public:
    TreeNode* Build(const vector<int>& preorder, const vector<int>& inorder, int pl, int pr, int il, int ir) {
    
    
        if (pl > pr || il > ir) {
    
    
            return nullptr;
        }
        //左子树中的节点数目=当前节点在中序序列的位置-中序序列的起始下标
        int k = pos[preorder[pl]] - il;
        
        // 建立根节点        
        TreeNode* root = new TreeNode(preorder[pl]);

     
        // 递归地构造左子树,并连接到根节点
        // 先序遍历中「从 左边界+1 开始的 k」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
        root->left = Build(preorder, inorder, pl + 1, pl + k, il, il + k - 1);
        // 递归地构造右子树,并连接到根节点
        // 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
         root->right = Build(preorder, inorder, pl + k + 1, pr, il + k + 1, ir);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    
    
        //获取节点个数n
        int n = preorder.size();
        //通过哈希表来存储中序序列节点位置
        for (int i = 0; i < n; i++) {
    
    
            pos[inorder[i]] = i;
        }
        //调用二叉树的构建,切片操作
        return Build(preorder, inorder, 0, n - 1, 0, n - 1);
    }
};

時間/空間の複雑さ: O(n);

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

タイトル説明[中]:

2 つの整数配列 inorder と postorder が与えられた場合、 inorder はバイナリ ツリーの inorder走査であり、 postorder は同じツリーのpostorder 走査です。このバイナリ ツリーを構築して返してください。

例 1:
入力: inorder = [9,3,15,20,7]、postorder = [9,15,7,20,3]

出力: [3,9,20,null,null,15,7]
2

アイデア [再帰]:

この質問では例 1 を例として取り上げます。彼の順序シーケンスは [9,3,15,20,7]、後順序シーケンスは [9,15,7,20,3] です。これら 2 つのプロパティに従って、シーケンス、事後シーケンスの最後の要素がルート ノードであることがわかっており、その後、順序シーケンスを通じて、左側のサブツリーの順序トラバーサルが [9] であることがわかり、右側のサブツリーの順序トラバーサルが [15,20] であることがわかります。 、7]。したがって、左側のサブツリーのポストオーダー シーケンスは 9 で、右側のサブツリーのポストオーダー シーケンスは [15, 7, 20] になります。これらのシーケンスを通じて左と右のサブツリーを再帰的に構築し、バイナリ ツリーを構築できます。

C++ コード:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    
    
     //定义一个哈希表
    unordered_map<int, int> pos;
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
    
    
     //获取节点个数n
        int n = inorder.size();
        //通过哈希表来存储中序序列节点位置
        for (int i = 0; i < n; i++) {
    
    
            pos[inorder[i]] = i;
        }
        //调用二叉树的构建,切片操作
        return Build(inorder, postorder, 0, n - 1, 0, n - 1);
    }
       TreeNode* Build(vector<int>& inorder,  vector<int>& postorder, int il, int ir, int pl, int pr) {
    
    
        if (pl > pr || il > ir) {
    
    
            return nullptr;
        }
        //左子树中的节点数目=当前节点在中序序列的位置-后序序列的末下标
        int k = pos[postorder[pr]] - il;
        
        // 建立根节点        
        TreeNode* root = new TreeNode(postorder[pr]);

     
        // 递归地构造左子树,并连接到根节点
        // 先序遍历中「从 左边界 开始的 k - 1」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
        root->left = Build(inorder, postorder,il, il + k - 1, pl, pl + k - 1);
        // 递归地构造右子树,并连接到根节点
        // 先序遍历中「从 左边界+左子树节点数目+1 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位 到 右边界-1」的元素
         root->right = Build(inorder, postorder, il + k + 1, ir, pl + k , pr - 1);
        return root;
    }
};

時間/空間の複雑さ: O(n);

112. パスの合計

タイトル説明[簡単]:

バイナリ ツリーのルート ノード root と、ターゲットの合計を表す整数の targetSum が与えられます。ツリー内にルート ノード、このパス上のすべてのノード値の合計が target と targetSum に等しいかどうかを判断します。存在する場合は true を返し、存在しない場合は false を返します。

リーフ ノードは、子ノードを持たないノードです。
例 1:
3

キー:root = [5,4,8,11,null,13,4,7,2,null,null,null,1]、ターゲット合計 = 22

出力: true
説明: ターゲット合計に等しいルート ノードからリーフ ノードへのパスが上の図に示されています。

アイデア [再帰]:

この質問の判断の本質は、左サブツリーまたは右サブツリーで、パス長が target の値であるパスを見つけることです。
タイトルを次のように変換します: target == root->val

C++ コード:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    
    
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
    
    
        if(root == nullptr)
        return false;
        if(root -> left == nullptr && root -> right == nullptr)
        return root->val == targetSum;
        return hasPathSum(root->left,targetSum - root->val) || hasPathSum(root->right,targetSum - root->val);
    }
};

時間/空間の複雑さ: O(n);

Supongo que te gusta

Origin blog.csdn.net/Lailalalala/article/details/126161062
Recomendado
Clasificación