101. バランスの取れた二分木
タイトル説明[簡単]:
与えられた二分木が、高さのバランスがとれた二分木であるかどうかを判断します。
この質問では、高さバランスの取れた二分木は、二分木の各ノードの左右のサブツリー間の高さの差の絶対値が 1 を超えないものとして定義されます。
例 1:
入力: root = [3,9,20,null,null,15,7]
出力: true
アイデア [再帰]:
二重カウントを避けるために、ここでは二分木の事後探索を使用します。
最初に左側のサブツリーをチェックして左側のサブツリーの高さ 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
アイデア [再帰]:
最小の深さを見つけることは、実際には、ルート ノードからリーフ ノードまでの最短のパス長を見つけることです。
この質問に答えるには、レイヤー順序のトラバーサル、幅優先、長さ優先の方法を使用できます。
しかし、この問題を解決するには、単純に再帰と三項演算を使用することができます。(ただし、このメソッドは実行時間とメモリ時間が大きくなります)
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);