LeetCode[110/102/111] バランスのとれたバイナリ ツリー、バイナリ ツリーの層順序トラバーサル、バイナリ ツリーの最小深さ C/C++——第 2 週 III

101. バランスの取れた二分木

タイトル説明[簡単]:

与えられた二分木が、高さのバランスがとれた二分木であるかどうかを判断します。


この質問では、高さバランスの取れた二分木は、二分木の各ノードの左右のサブツリー間の高さの差の絶対値が 1 を超えないものとして定義されます。

例 1:
入力: root = [3,9,20,null,null,15,7]
出力: true
1

アイデア [再帰]:

二重カウントを避けるために、ここでは二分木の事後探索を使用します。
最初に左側のサブツリーをチェックして左側のサブツリーの高さ L を取得し、
次に右側のサブツリーをチェックして右側のサブツリーの高さ R を取得し、
最後に L と R の差が ≤ 1 であるかどうかを確認し、≤ 1 の場合は次の条件を確認します。バランスの取れた二分木が満たされます。(ここでは abs() を使用して差分計算を実行できます)

C++ コード:

解決策 1:

/**
 * 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 isBalanced(TreeNode* root) {
    
    
        return getheigh(root) >= 0;

    }
    int getheigh(TreeNode* root){
    
    
        if(root == nullptr)//其他表示二叉树的高度
        return 0;
        int lefth = getheigh(root -> left);//求左子树高度
        int righth = getheigh(root -> right);//求右子树高度
        if(abs(lefth-righth) <= 1 && lefth >= 0 && righth >=0 ){
    
    
       return max(lefth,righth) + 1;
       } 
       else{
    
    
           return -1;//用-1来表示二叉树不平衡的情况
       }
    }
};

解決策 2:

class Solution {
    
    
public:
    bool isBalanced(TreeNode* root) {
    
    
        return getheigh(root) != -1;

    }
    int getheigh(TreeNode* root){
    
    
        if(root == nullptr)//其他表示二叉树的高度
        return 0;
        int lefth = getheigh(root -> left);//求左子树高度
        if(lefth == -1)
        return -1;//用-1来表示二叉树不平衡的情况
        int righth = getheigh(root -> right);//求右子树高度
        if(righth == -1)
        return -1;
        if(abs(lefth-righth) > 1 )
        return -1;

       return max(lefth,righth) + 1;
        
    }
};

時間計算量: O(n);

102. 二分木のレベル順走査

タイトル説明[中]:

バイナリ ツリーのルート ノード ルートを指定すると、そのノード値のレベル順序の走査を返します。(つまり、レイヤーごとに、左から右にすべてのノードを訪問します)。

例 1:
入力: root = [3,9,20,null,null,15,7]

出力: [[3]、[9,20]、[15,7]]
ここに画像の説明を挿入

アイデア [キューを使用した BFS トラバーサル]:

最初にルート ノードをキューに入れます
。 1. キュー内の要素の数 (count) を取得します (その後、左右の子がキューに参加する必要があるため、区別するために count を使用する必要があります) 2. すべてのノードをポップアップします
。 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 {
    
    
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
    
    
        vector<vector<int>> res;
        if (root == nullptr) ///若根节点为空,直接返回0
        return res;

        queue<TreeNode*> q; //定义一个队列
        q.push(root);//添加根节点

        while(!q.empty()) {
    
    //当队列非空
            int count = q.size();//获取队列节点数量,即当前节点数
            //现在队列中存储的就是当前队列的全部节点,我们现在要将他们全部取出来存到数组里就好了
            vector<int> c;//定义存储全部节点的数组
            for (int i = 0; i < count; i++) {
    
    
                TreeNode* node = q.front(); 
                q.pop();
               c.push_back(node->val);//把弹出的节点加到数组中
                if (node->left)    //否则把他们左右孩子加进来
                q.push(node->left);
                if (node->right)  
                q.push(node->right);
            }
            res.push_back(c);//每加完一层,层数都要加1
        }

        return res;
    }
};

時間計算量: O(n);

111. 二分木の最小深さ

タイトル説明[簡単]:

二分木が与えられた場合、その最小の深さを見つけます。

最小深さは、ルート ノードから最も近いリーフ ノードまでの最短パス上のノードの数です。

注: リーフ ノードは、子ノードを持たないノードを指します。

例 1:

入力: root = [3,9,20,null,null,15,7]

出力: 2

2

アイデア [再帰]:

最小の深さを見つけることは、実際には、ルート ノードからリーフ ノードまでの最短のパス長を見つけることです。
この質問に答えるには、レイヤー順序のトラバーサル、幅優先、長さ優先の方法を使用できます。

しかし、この問題を解決するには、単純に再帰と三項演算を使用することができます。(ただし、このメソッドは実行時間とメモリ時間が大きくなります)

C++ コード:

アイデア 1 [再帰 + 三眼視操作]:

/**
 * 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:
    int minDepth(TreeNode* root) {
    
    
        if(root == nullptr)
            return 0;
        int left=minDepth(root->left)
        int right=minDepth(root->right);
        return (left && right) ? 1+min(left,right) : 1 + left + right;
    }
};

三項演算子では、左端の条件 ( left && right)により、実際に 1 + left + right が実行されるとき、ノードには最大 1 つのサブツリー( +1リーフノード(1 + 0 + 0) として。

アイデア 2 [DFS]:

class Solution {
    
    
public:
    int minDepth(TreeNode* root) {
    
    
        // 判断是不是空树,只有第一次有用,后面递归用不到
        if (root ==nullptr)   
        return 0;
        // 说明为叶子节点,深为1
        if (root->left == nullptr && root->right == nullptr)
        return 1;
        // 左空右不空,返回右子树深度且+1
        if (root->left == nullptr)    
        return minDepth(root->right) + 1;
        // 右空左不空,返回左子树深度且+1
        if (root->right == nullptr)   
        return minDepth(root->left) + 1;
        // 左右都不空,返回左右子树深度较小值且+1
        return min(minDepth(root->left), minDepth(root->right)) + 1; // 判断是不是空树,但只在第一次遍历时使用
    }
};

アイデア 3 [レベル シーケンスのトラバーサル]:

class Solution {
    
    
public:
    int minDepth(TreeNode* root) {
    
    
        if (root == nullptr) ///若根节点为空,直接返回0
        return 0;

        queue<TreeNode*> q; //定义一个队列
        q.push(root);//添加根节点

        int res = 1;//定义一下结果遍历,初始深度为1

        // 层数从1开始,到了当前层找到叶子节点,那答案就是当前层数
        while(!q.empty()) {
    
    //当队列非空
            int count = q.size();//获取队列节点数量,即当前节点数
            for (int i = 0; i < count; i++) {
    
    //弹出
                TreeNode* node = q.front(); //帮他们把左右孩子加入进来
                q.pop();
                if (node->left == nullptr && node->right == nullptr)   //如果弹出的是叶子节点,就可以直接返回结果
                return res;
                if (node->left)    //否则把他们左右孩子加进来
                q.push(node->left);
                if (node->right)  
                q.push(node->right);
            }
            res++;//每加完一层,层数都要加1
        }

        return res;

    }
};

時間計算量: O(n);

Guess you like

Origin blog.csdn.net/Lailalalala/article/details/126150537