深度与高度
- 深度是到根节点的距离。求解应该自顶向下,用前序遍历
- 高度是到叶子节点的距离。求解应该自底向上,用后序遍历
- 根节点的高度 等价于 二叉树的最大深度
104.二叉树的最大深度
深度遍历一:遍历的思想 + 回溯
遍历二叉树,同时使用额外的变量来维护结果
class Solution {
int max = 0;
int depth = 0;
public int maxDepth(TreeNode root) {
traverse(root);
return max;
}
public void traverse(TreeNode root){
if(root == null) return ;
depth++;
if(root.left == null && root.right == null) max = depth > max ? depth: max; //叶子节点
traverse(root.left);
traverse(root.right);
depth--;
}
}
深度遍历二:子问题的思想 + 递推表达式
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
return 1 + Math.max(maxDepth(root.left),maxDepth(root.right));
}
}
层次遍历,迭代解法
class Solution {
public int maxDepth(TreeNode root) {
Deque<TreeNode> que = new ArrayDeque<>();
if(root!=null) que.offerFirst(root);
int max = 0;
while(!que.isEmpty()){
int size = que.size();
while(size-->0){
TreeNode cur = que.pollLast();
if(cur.left!=null) que.offerFirst(cur.left);
if(cur.right!=null) que.offerFirst(cur.right);
}
max++;
}
return max;
}
}
559. N 叉树的最大深度
//深度遍历一:遍历的思想 + 回溯
class Solution {
int max = 0;
int depth = 0;
public int maxDepth(Node root) {
traverse(root);
return max;
}
public void traverse(Node root){
if(root == null) return ;
depth++;
if(root.children.size() == 0) max = Math.max(depth,max); //叶子节点
for(Node child: root.children){
traverse(child);
depth--;
}
}
}
//深度遍历二:子问题的思想 + 递推表达式
class Solution {
public int maxDepth(Node root) {
if(root == null) return 0;
int max = 0;
for(Node child: root.children){
max = Math.max(maxDepth(child),max);
}
return max + 1;
}
}
//层次遍历
class Solution {
public int maxDepth(Node root) {
Deque<Node> que = new ArrayDeque<>();
if(root != null) que.offerFirst(root);
int max = 0;
while(!que.isEmpty()){
int size = que.size();
while(size -- > 0){
Node cur = que.pollLast();
for(Node child: cur.children) que.offerFirst(child);
}
max++;
}
return max;
}
}
111.二叉树的最小深度
//深度遍历一:遍历的思想 + 回溯
class Solution {
int depth = 0;
int min = 100010;
public int minDepth(TreeNode root) {
if(root == null) return 0;
traverse(root);
return min;
}
public void traverse(TreeNode root){
if(root == null) return;
depth++;
if(root.left == null && root.right == null) min = depth < min ? depth : min;
traverse(root.left);
traverse(root.right);
depth--;
}
}
//深度遍历二:子问题的思想 + 递推表达式
class Solution {
public int minDepth(TreeNode root) {
if(root == null) return 0;
int leftmin = minDepth(root.left);
int rightmin = minDepth(root.right);
//特殊情况,一方子树为空,另一方不为空
if( root.left == null && root.right != null) return rightmin + 1;
if( root.right == null && root.left != null) return leftmin + 1;
return Math.min(leftmin,rightmin) + 1;
}
}
//层次遍历
class Solution {
public int minDepth(TreeNode root) {
Deque<TreeNode> que = new ArrayDeque<>();
if(root == null) return 0;
que.offerFirst(root);
int depth = 0;
while(!que.isEmpty()){
int size = que.size();
depth++;
while(size-- > 0){
TreeNode cur = que.pollLast();
if(cur.left == null && cur.right == null) return depth; //从上往下遍历,第一个叶子节点就是最小深度
if(cur.left!=null) que.offerFirst(cur.left);
if(cur.right!=null) que.offerFirst(cur.right);
}
}
return depth;
}
}
222. 完全二叉树的节点个数
普通二叉树解法
//深度遍历,子问题的解法
class Solution {
public int countNodes(TreeNode root) {
if(root == null) return 0;
return countNodes(root.left) + countNodes(root.right) + 1;
}
}
//深度遍历,遍历的解法
class Solution {
int res;
public int countNodes(TreeNode root) {
if(root == null) return 0;
return countNodes(root.left) + countNodes(root.right) + 1;
}
public void traverse(TreeNode root){
if(root == null) return ;
if(root != null) res++;
traverse(root.left);
traverse(root.right);
}
}
//层次遍历
class Solution {
public int countNodes(TreeNode root) {
if(root == null) return 0;
Deque<TreeNode> que = new ArrayDeque<>();
que.offerFirst(root);
int res = 0;
while(!que.isEmpty()){
TreeNode cur = que.pollLast();
res++;
if(cur.left!=null) que.offerFirst(cur.left);
if(cur.right!=null) que.offerFirst(cur.right);
}
return res;
}
}
利用完全二叉树的性质
完全二叉树两种情况:
- 满二叉树,用公式 2 n − 1 2^n-1 2n−1计算,n为树的高度;
- 最后一层叶子不满。这种情况则分布递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1进行计算。
判断一个树是否为满二叉树:利用满二叉树的性质,递归向左遍历的深度等于递归向右遍历的深度。
//后序遍历
class Solution {
public int countNodes(TreeNode root) {
if(root == null) return 0; // 节点为空返回
TreeNode l = root.left;
TreeNode r = root.right;
int llen = 0;
int rlen = 0;
while(l != null){
llen++;
l = l.left;
}
while(r != null){
rlen++;
r = r.right;
}
//当前树为完全二叉树则利用公式直接计算
if(llen == rlen) return (2 << llen) - 1;
return 1 + countNodes(root.left) + countNodes(root.right);
}
}