1.トピック
二分木が与えられた場合、それが高度にバランスの取れた二分木であるかどうかを判断します。
この質問では、バランスの取れた二分木は次のように定義されます。
二分木の各ノードの左右のサブツリー間の高さの差の絶対値は1を超えません。
例1:
输入:root = [3,9,20,null,null,15,7]
输出:true
例2:
输入:root = [1,2,2,3,3,null,null,4,4]
输出:false
例3:
输入:root = []
输出:true
促す:
- ツリー内のノードの数は[0、5000]の範囲です。
- -104 <= Node.val <= 104
二、解く
このツリーの深さ=最大{左のサブツリーの深さ、右のサブツリーの深さ} + 1
1.注文後のトラバーサル+剪定(下から上へ)
アイデア:
二分木を横断した後、サブツリーの深さを下から上に戻します。特定のサブツリーがバランスの取れたツリーではないと判断された場合は、剪定し(最初は考えにくい)、直接上に戻ります。
アルゴリズムflow-recur(root)関数:
- 戻り値:
- ノードルートの左/右サブツリー間の深さの差が<= 1の場合:現在のサブツリーの深さ、つまりノードルートの左/右サブツリーの最大深さを返します+ 1(max(left、right )+ 1)
- ノードルートの左右のサブツリーの深さの差が2より大きい場合、-1が返されます。これは、このサブツリーが平衡ツリーではないことを意味します。
- 終了条件:
- ルートが空の場合:リーフノードが交差していることを意味するため、高さは0です。
- 左/右サブツリーの深さが-1の場合、左/右サブツリーが平衡ツリーではないことを意味するため、剪定すると、直接-1が返されます。
isBalanced(root)関数:
- 戻り値:recur(root)!= -1の場合、ツリーのバランスが取れていることを意味し、trueを返します。それ以外の場合はfalseを返します。
コード:
class Solution {
public boolean isBalanced(TreeNode root) {
return recur(root) != -1;
}
private int recur(TreeNode root) {
// 1、Current logic
if (root == null) return 0;
// 3、Drill down
int left = recur(root.left);
// 2、Current logic
if(left == -1) return -1;
// 3、Drill down
int right = recur(root.right);
// 2、Current logic
if(right == -1) return -1;
return Math.abs(left - right) < 2 ? Math.max(left, right) + 1 : -1;
}
}
時間計算量: O(n)O(n)O (n )
スペースの複雑さ: O(n)O(n)O (n )
2.トラバーサル+判定深度の事前注文(上から下へ)
アイデア:
関数depth(root)を作成して、現在のサブツリーの深さを取得し(つまり、質問55-I。バイナリツリーの深さをインタビューします)、左側との深さの差を比較してabs(depth(root.left) - depth(root.right)) <= 1
、特定のサブツリーがバイナリであるかどうかを判断します。特定のサブツリーの右側のサブツリー。バランスツリー。すべてのサブツリーのバランスが取れている場合、サブツリーのバランスが取れています。
より具体的なプロセスについては説明しません。参考文献1を参照してください。基本は良いです、あなたはコードコメントと一緒にそれを理解することができます。
コード:
- バージョン1:
class Solution {
public boolean isBalanced(TreeNode root) {
// 1、Terminator
if (root == null) return true;
// 2 && 3、Current logic && Drill down
return Math.abs(depth(root.left) - depth(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
private int depth(TreeNode root) {
if (root == null) return 0;
return Math.max(depth(root.left), depth(root.right)) + 1;
}
}
- バージョン2:
class Solution {
public boolean isBalanced(TreeNode root) {
return judge(root);
}
public boolean judge(TreeNode root) {
if (root == null) return true;
if (Math.abs(height(root.left)-height(root.right)) > 1) return false;
else return judge(root.left) && judge(root.right);
}
public int height(TreeNode root) {
if (root == null) return 0;
return Math.max(height(root.left), height(root.right)) + 1;
}
}
時間計算量: O(nlogn)O(nlogn)O (n l o g n )
完全な二分木の高さの複雑さO(logn)O(logn)O (l o g n )、各レベルでトラバースされるノードの数はn,(n-1)/2*2,(n-3)/4*4,(n-7)/8*8,...,1*(n+1)/2
です。
全体的な時間計算量=各レイヤーの実行の複雑さ*レイヤーの数の複雑さ=O(nlogn)O(nlogn)O (n l o g n )。
スペースの複雑さ: O(n)O(n)O (n )