104.二叉树的最大深度
链接
题目链接
文章链接
第一想法
题目要求找出二叉树的最大深度,所以就是可以用层序法,最大深度就是层序法的层数,代码如下:
function maxDepth(root: TreeNode | null): number {
let queue:TreeNode[]=[]
let res:number=0
if(root) queue.push(root)
while(queue.length>0){
let size:number=queue.length
while(size--){
let node:TreeNode=queue.shift()!
if(node.left) queue.push(node.left)
if(node.right) queue.push(node.right)
}
res++
}
return res
};
第二种方法就是递归法,通过比较每个叶子节点的深度来判断出最大深度:
function maxDepth(root: TreeNode | null): number {
let res:number=0
const dfs:(root: TreeNode | null,number:number)=>void=(root: TreeNode | null,number:number)=>{
if(root==null){
res=Math.max(res,number)
return
}
//中其实就是下面的number+1
dfs(root.left,number+1) //左
dfs(root.right,number+1) //右
}
//这里从0开始是因为终止条件是默认加了1
dfs(root,0)
return res
};
看完文章后的想法
文章用了前序遍历,后序遍历和层序遍历,核心思想都是一样的,下面是后序遍历的代码:
function maxDepth(root: TreeNode | null): number {
const dfs:(root: TreeNode | null)=>number=(root: TreeNode | null)=>{
if(root==null) return 0;
//中其实就是下面的number+1
let left:number=dfs(root.left) //左
let right:number=dfs(root.right) //右
return 1+Math.max(left,right) //选择左右子树最大的深度返回
}
return dfs(root)
};
思考
这道题不难,我认为比较好理解的是层序遍历,但是前序遍历和后序遍历代码比较简洁,核心思想就是二叉树的最大深度就是根节点的最大高度。题(559. N 叉树的最大深度 - 力扣(Leetcode))也是相同的道理,下面展示不同的解法:
层序
function maxDepth(root: Node | null): number {
let queue:(Node | null)[]=[]
let number:number=0
if(root) queue.push(root)
while(queue.length>0){
let size:number=queue.length
while(size--){
let node=queue.shift()!
queue.push(...node.children)
}
number++
}
return number
};
前序
function maxDepth(root: Node | null): number {
let res:number=0
const dfs:(root: Node | null,number:number)=>void=(root: Node | null,number:number)=>{
if(root==null){
res=Math.max(number,res)
return
}
//这个条件是用了进入终止条件的 因为用for的话 children=[]时不执行dfs 所以增加这个条件用于执行dfs
if(root.children.length==0) dfs(null,number+1);
for(let node of root.children){
dfs(node,number+1)
}
}
dfs(root,0)
return res
};
后序
function maxDepth(root: Node | null): number {
let res:number=0
const dfs:(root: Node | null)=>number=(root: Node | null)=>{
if(!root) return 0 //这个是防止root=[]的情况
if(root.children.length==0) return 1;
let max:number=0
for(let node of root.children){
max=Math.max(max,dfs(node))
}
return max+1
}
return dfs(root)
};
111. 二叉树的最小深度
链接
文章链接
题目链接
第一想法
最简单的还是利用层序遍历,当最先开始left和right都为null时就是最浅深度,代码如下:
function minDepth(root: TreeNode | null): number {
let queue:TreeNode[]=[]
let res:number=0
if(root) queue.push(root)
while(queue.length>0){
let size:number=queue.length
while(size--){
let node:TreeNode=queue.shift()!
if(node.left) queue.push(node.left)
if(node.right) queue.push(node.right)
if(!node.left&&!node.right) return res+1
}
res++
}
return 0
};
尝试用前序和后序遍历一下:
前序:
function minDepth(root: TreeNode | null): number {
if(!root) return 0
let min:number=Number.MAX_SAFE_INTEGER
const dfs:(root:TreeNode | null,number:number)=>void=(root:TreeNode | null,number:number)=>{
if(!root?.left&&!root?.right){
min=Math.min(min,number)
return
}
if(root.left) dfs(root.left,number+1)
if(root.right)dfs(root.right,number+1)
}
dfs(root,1)
return min
};
后序:
function minDepth(root: TreeNode | null): number {
if(!root) return 0
const dfs:(root:TreeNode | null)=>number=(root:TreeNode | null)=>{
if(!root!.left&&!root!.right) return 1;
let left:number=Number.MAX_SAFE_INTEGER
let right:number=Number.MAX_SAFE_INTEGER
if(root!.left) left=dfs(root!.left)
if(root!.right) right=dfs(root!.right)
return 1+Math.min(left,right)
}
return dfs(root)
};
看完文章后的想法
代码随想录中也用了前序遍历、后序遍历以及层序遍历,其中前序遍历和层序遍历是一样的,但是后序遍历是有所不同的,我的解法中是用root.left和root.right都不存在时才是子节点,也就是这个条件if(!root!.left&&!root!.right) return 1;,下面给出代码随想录中的解法:
function minDepth(root: TreeNode | null): number {
if (root === null) return 0;
if (root.left !== null && root.right === null) { //右节点存在而左节点不存在,所以最小深度为 1 + minDepth(root.left);
return 1 + minDepth(root.left);
}
if (root.left === null && root.right !== null) {
return 1 + minDepth(root.right);
}
//左右节点都存在
return 1 + Math.min(minDepth(root.left), minDepth(root.right));
}
思考
这道题也不难,但是其中有一点比较容易踩坑,就是不能按照二叉树的最大深度来计算,因为最大深度是求最后一层的节点,肯定是是叶子节点,但是求最浅深度,当一个节点有左孩子但是没有右孩子,而它不是叶子节点,就是代码随想录中的这张图:
222. 完全二叉树的节点个数
链接
文章链接
题目链接
第一想法
还是最简单的利用层序遍历,代码如下:
function countNodes(root: TreeNode | null): number {
let queue:(TreeNode | null)[]=[]
let res:number=0
if(root) queue.push(root)
while(queue.length>0){
let node=queue.shift()!
if(node.left) queue.push(node.left)
if(node.right) queue.push(node.right)
res++
}
return res
};
递归法也是可以的,这里我用的是前序遍历:
function countNodes(root: TreeNode | null): number {
let res:number=0
const dfs:(root: TreeNode | null)=>void=(root: TreeNode | null)=>{
if(root==null) return;
res++
dfs(root.left)
dfs(root.right)
}
dfs(root)
return res
};
看完文章后的想法
我所用的方法都是都是可以解决普通二叉树的方法,但是文章用了一种方法,他的核心思想就是利用完全二叉树的性质,满足完全二叉树,则递归它的左右孩子,最终一定会出现满二叉树,这是代码随想录中的图片:
所以递归方法为如果左右子树的深度都相同,那么就是一棵满二叉树,如图:
这种情况就不是满二叉树:
代码如下:
function countNodes(root: TreeNode | null): number {
const dfs:(root: TreeNode | null)=>number=(root: TreeNode | null)=>{
if(root==null) return 0;
let left:number=0
let right:number=0
let curr:TreeNode|null=root
while(curr){
left++
curr=curr.left
}
curr=root
while(curr){
right++
curr=curr.right
}
if(left===right) return 2**left-1 //如果是满二叉树则返回节点个数
return 1+dfs(root.left)+dfs(root.right) //不满足满二叉树就往下继续递归,返回左节点个数+右节点个数+当前节点
}
return dfs(root)
};
思考
这道题如果按照一般二叉树来写是比较容易写出来的,但是利用完全二叉树的性质来计算是没想到的,其中一个核心就是完全二叉树的左右节点的终止一定满足满二叉树,上文中已经提到。所以这道题要学习利用完全二叉树来解决这个问题。
总结
今天一共四道题,耗时2.5小时,其中没想到以及需要学习的就是最后一道题(222题)学习利用完全二叉树的性质来解决这道题