一、力扣题104. 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树[3,9,20,null,null,15,7]
,3 / \ 9 20 / \ 15 7返回它的最大深度 3 。
方法一:递归法
递归参数:二叉树节点;终止条件:节点为空;返回参数:该节点的深度。
因为返回参数是当前节点的深度,父节点要获取当前深度,就需要拿到子节点的深度再加1,所以实际上就是从最底层的节点开始返回深度,每个父节点的深度都是子节点深度加1,但一个节点一般有左右两个子节点,故需对比两个子节点的深度,取深度更大的那个加1。
所以单层递归逻辑是:先判断当前节点是否为空,为空return 0,不为空则继续,分别递归左右两个节点,将返回的左右节点的深度做对比,取更大的深度depth + 1 然后返回给上面的父节点。
function maxDepth($root) {
if(!$root) return 0;
$left = $this->maxDepth($root->left);
$right = $this->maxDepth($root->right);
return 1 + max($left, $right);
}
方法二:递归法2
二叉树的最大深度是根节点到叶子节点的最大节点数,也就是求最远叶子节点的深度。换句话说,根节点的高度就是二叉树的最大高度,等于最远叶子节点的最大深度,所以可以直接求根节点的最大高度。
这次的逻辑是从上往下,每下到一个节点就加1,所以把深度设为递归的参数,将最大深度max改为全局变量,最大深度 max 的初始值的整型里的最小值,方便一开始的对比。
递归参数:当前节点和深度; 终止条件:当前节点为空; 无返回参数。
单层递归逻辑:先判断当前深度是否比全局变量的最大深度 max 大,是的话就把 max 改为当前深度。 然后将深度 + 1,递归存在的子节点。
class Solution {
private $result = 1;
/**
* @param TreeNode $root
* @return Integer
*/
function maxDepth($root) {
if(!$root) return 0;
$this->max($root, 1);
return $this->result;
}
function max($root, $depth) {
if($depth > $this->result) $this->result = $depth;
if($root->left) {
$depth++;
$this->max($root->left, $depth);
$depth--;
}
if($root->right) {
$depth++;
$this->max($root->right, $depth);
$depth--;
}
}
}
方法三:迭代法
使用层序遍历,每遍历一层深度+1即可。
function maxDepth($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
$sum = 0;
while(!$queue->isEmpty()) {
$size = $queue->count();
$sum++;
while($size--) {
$cur = $queue->dequeue();
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
}
return $sum;
}
二、力扣题111. 二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:2
示例 2:
输入:root = [2,null,3,null,4,null,5,null,6] 输出:5
提示:
- 树中节点数的范围在
[0, 105]
内 -1000 <= Node.val <= 1000
方法一:递归法
和上面的递归法逻辑差不多,不同之处在于返回的深度是取左右节点中更小的深度+1,另外只递归存在的节点,不会递归不存在 的节点,递归不存在的节点会影响min()函数的判断。
function minDepth($root) {
if(!$root) return 0;
return $this->min($root);
}
function min($root) {
if($root->left === null && $root->right === null) return 1;
if($root->left && $root->right) {
$left = $this->min($root->left);
$right = $this->min($root->right);
return 1 + min($left, $right);
}
if($root->left) return $this->min($root->left) + 1;
if($root->right) return $this->min($root->right) + 1;
}
也有更简洁的写法
function minDepth($root) {
if(!$root) return 0;
return $this->min($root);
}
function min($root) {
if($root->left === null && $root->right === null) return 1;
$left = $this->minDepth($root->left);
$right = $this->minDepth($root->right);
if($root->left && $root->right) {
return 1 + min($left, $right);
}
if($root->left) return $left + 1;
return $right + 1;
}
方法二:递归法2
逻辑和最大深度的递归法2没有区别,同样设置一个全局变量 min ,初始值为整型里的最大值,然后在递归中不断对比获取更小的深度,终止条件依旧为节点是叶子节点的时候。
class Solution {
private $result = PHP_INT_MAX;
/**
* @param TreeNode $root
* @return Integer
*/
function minDepth($root) {
if(!$root) return 0;
$this->res($root, 1);
return $this->result;
}
function res($root, $depth) {
if($root->left === null && $root->right === null) {
$this->result = min($depth, $this->result);
return;
}
if($root->left) {
$this->res($root->left, $depth + 1);
}
if($root->right) {
$this->res($root->right, $depth + 1);
}
return;
}
}
方法三:迭代法
使用层序遍历,每遍历一层深度都 + 1,知道遍历到的节点为叶子节点时,直接返回当前深度即可。
function minDepth($root) {
$queue = new splQueue();
if(!$root) return 0;
$queue->enqueue($root);
$sum = 0;
while(!$queue->isEmpty()) {
$size = $queue->count();
$sum++;
while($size--) {
$cur = $queue->dequeue();
if($cur->left === null && $cur->right === null) {
return $sum;
}
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
}
}
三、力扣题222. 完全二叉树的节点个数
给你一棵 完全二叉树 的根节点 root
,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~ 2h
个节点。
示例 1:
输入:root = [1,2,3,4,5,6] 输出:6
示例 2:
输入:root = [] 输出:0
示例 3:
输入:root = [1] 输出:1
提示:
- 树中节点的数目范围是
[0, 5 * 104]
0 <= Node.val <= 5 * 104
- 题目数据保证输入的树是 完全二叉树
方法一:迭代法
这道题直接用层序遍历是最容易想到的,直接每将一个节点入队列时,总和就加一,当判断到空节点时,直接return即可。
unction countNodes($root) {
if(!$root) return 0;
$queue = new splQueue();
$queue->enqueue($root);
$sum = 0;
while(!$queue->isEmpty()) {
$size = $queue->count();
$sum += $size;
while($size--) {
$cur = $queue->dequeue();
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
}
return $sum;
}
方法二:递归法
使用全局变量统计节点个数,递归节点时遵循左、右节点的顺序,因为是完全二叉树,当递归到空节点时,说明全部节点已经遍历完毕,直接return。
class Solution {
private $sum = 0;
/**
* @param TreeNode $root
* @return Integer
*/
function countNodes($root) {
if(!$root) return 0;
$this->sum++;
$this->countNodes($root->left);
$this->countNodes($root->right);
return $this->sum;
}
}
方法三:递归法2
看题解的,非常简洁,简洁到一开始看着没有头绪,然后神奇地发现这样真的可以。
function countNodes($root) {
if(!$root) return 0;
return 1 + $this->countNodes($root->left) + $this->countNodes($root->right);
}