提示:努力生活,开心、快乐的一天
文章目录
104.二叉树的最大深度
💡解题思路
递归法
:可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度,根节点的高度就是二叉树的最大深度
,所以通过后序求的根节点高度来求的二叉树最大深度。递归的三部曲如下:- 确定递归函数的参数和返回值:参数就是传入树的根节点
- 确定终止条件:如果为空节点的话,就返回0,表示高度为0
- 确定单层递归的逻辑:
先求它的左子树的深度,再求右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度
迭代法(层序遍历)
:一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度
🤔遇到的问题
- 终止条件,root===null,return的是0不是null
💻代码实现
递归法(后序遍历)
var maxDepth = function (root) {
//使用递归的方法 递归三部曲
//1. 确定递归函数的参数和返回值
const getdepth = function (node) {
//2.确定终止条件
if (!node) return 0
//3.单层遍历逻辑
let leftNode = maxDepth(node.left)
let rightNode = maxDepth(node.right)
let size = 1 + Math.max(leftNode, rightNode)
return size
}
return getdepth(root)
};
迭代法(层序遍历)
var maxDepth = function (root) {
let size = 0
if(!root) return size
let queue = [root]
while (queue.length) {
let len = queue.length
//层数+1
size++
for (let i = 0; i < len; i++){
let node = queue.shift()
node.left && queue.push(node.left)
node.right &&queue.push(node.right)
}
}
return size
};
🎯题目总结
- 二叉树节点的深度:指从
根节点到该节点
的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始) - 二叉树节点的高度:指从
该节点到叶子节点
的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
559.n叉树的最大深度
💡解题思路
- 与求二叉树的最大深度基本相同,只是在递归或者遍历左右孩子的时候,此处需要
遍历每一个孩子
🤔遇到的问题
- 递归的时候,层数+1不能放在循坏中
- 迭代遍历模式有点模糊了
💻代码实现
递归法(后序遍历)
var maxDepth = function (root) {
//使用递归的方法 递归三部曲
//1. 确定递归函数的参数和返回值
const getdepth = (node) => {
//2.确定终止条件
if (!node) return 0
//3.单层遍历逻辑
let max = 0
for (const item of node.children) {
max = Math.max(max,getdepth(item))
}
return max+1
}
return getdepth(root)
};
迭代法(层序遍历)
var maxDepth = function (root) {
if (!root) return 0
let queue = []
queue.push(root)
let size = 0
while (queue.length) {
// 记录当前层级节点数
let len = queue.length
//层数+1
size++
for (let i = 0; i < len; i++){
let node = queue.shift()
//存放每一个孩子结点
for (const item of node.children) {
item&&queue.push(item)
}
}
}
return size
};
111.二叉树的最小深度
💡解题思路
最小深度是从根节点到最近叶子节点的最短路径上的节点数量 叶子节点,左右孩子都为空的节点才是叶子节点
递归法
:递归三部曲
- 确定递归函数的参数和返回值:参数为要传入的二叉树根节点
- 确定终止条件:终止条件也是遇到空节点返回0,表示当前节点的高度为0
- 确定单层递归的逻辑:如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度;反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1
迭代法
:只有当左右孩子都为空的时候,才说明遍历到最低点了
。如果其中一个孩子不为空则不是最低点
🤔遇到的问题
- 递归法:特殊情况的判断有问题
- 迭代法:只有当左右孩子都为空的时候,才说明遍历到最低点了
💻代码实现
递归法(后序遍历)
var minDepth = function (root) {
//使用递归的方法 递归三部曲
//1. 确定递归函数的参数和返回值
const getdepth = (node) => {
//2.确定终止条件
if (!node) return 0
let count = 0
//特殊情况
if (!node.left && node.right !== null) {
count = 1 + getdepth(node.right)
}
else if (!node.right && node.left !== null) {
count = 1 + getdepth(node.left)
} else if (!node.right && !node.left) {
count = count + 1
} else {
//3.单层遍历逻辑
//左、右、中
let leftNode = getdepth(node.left)
let rightNode = getdepth(node.right)
count = 1 + Math.min(leftNode, rightNode)
}
return count
}
return getdepth(root)
};
迭代法(层序遍历)
var minDepth = function (root) {
let count = 0
if (!root) return count
let queue = []
queue.push(root)
while (queue.length) {
let len = queue.length
count++
for (let i = 0; i < len; i++){
let node = queue.shift()
//当左右子结点都为空时,遍历结束
if (!node.left && !node.right) {
return count
}
node.left && queue.push(node.left)
node.right && queue.push(node.right)
}
}
};
🎯题目总结
求二叉树的最小深度
和求二叉树的最大深度
的差别主要在于处理左右孩子不为空的逻辑
- 迭代法只有当左右孩子都为空的时候,才说明遍历到最低点了
222.完全二叉树的节点个数
💡解题思路
- 按照普通二叉树的求法
- 递归法(后序遍历):确定递归函数的参数和返回值:参数就是传入树的根节点;确定终止条件:如果为空节点的话,就返回0,表示节点数为0;确定单层递归的逻辑:先求它的左子树的节点数量,再求右子树的节点数量,最后取总和再加一 (加1是因为算上当前中间节点)就是目前节点为根节点的节点数量
- 迭代法(层序遍历):模板少做改动,加一个变量result,统计节点数量就可以
- 利用完全二叉树性质的求法,依旧使用递归
- 完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
- 对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为
- 对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算
- 可以看出如果整个树不是满二叉树,就递归其左右孩子,直到遇到满二叉树为止,用公式计算这个子树(满二叉树)的节点数量
- 在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树
递归第二步:终止条件的写法,就会比较复杂,需要根据左深度和右深度是否相同来判断该子树是不是满二叉树
🤔遇到的问题
- 完全二叉树性质的求法,递归的终止条件判断失误
💻代码实现
普通二叉树:递归法(后序遍历)
var countNodes = function(root) {
const getNodeSize = (node)=>{
if(!node) return 0
let leftSize = getNodeSize(node.left)
let rightSize = getNodeSize(node.right)
return leftSize+rightSize+1
}
return getNodeSize(root)
};
普通二叉树:迭代法(层序遍历)
var countNodes = function(root) {
if(!root) return 0
let queue = []
let count = 0
queue.push(root)
while(queue.length){
let len = queue.length
for(let i=0;i<len;i++){
let node = queue.shift()
count++
node.left&&queue.push(node.left)
node.right&&queue.push(node.right)
}
}
return count
};
完全二叉树特性:递归法(后序遍历)
var countNodes = function(root) {
//利用完全二叉树的特点
const getNodeSize = (node)=>{
if(!node) return 0
// 开始根据左深度和右深度是否相同来判断该子树是不是满二叉树
let left = node.left
let right = node.right
let leftLength =0;
let rightLength = 0;
// 求左子树深度
while(left){
left = left.left
leftLength++
}
// 求右子树深度
while(right){
right = right.right
rightLength++
}
//当左右节点数相同,满二叉树
if(rightLength==leftLength){
return Math.pow(2, leftLength+1) - 1
}
//单层递归的逻辑 左右中
let leftNode = getNodeSize(node.left)
let rightNode = getNodeSize(node.right)
return leftNode+rightNode+1
}
return getNodeSize(root)
}
🎯题目总结
对完全二叉树有了更深的了解
🎈今日心得
递归遍历和层序遍历都能比较快的解决问题,越来熟练了