目录
前沿:撰写博客的目的是为了再刷时回顾和进一步完善,其次才是以教为学,所以如果有些博客写的较简陋,是为了保持进度不得已而为之,还请大家多多见谅。
预:看到题目后的思路和实现的代码。
见:参考答案展示。
感思:对比答案后的思考,与之前做过的题目是否有关联。
行:
(1)对于没做出来的题目,阅读答案后重新做一遍;
(2)下次做题可以尝试改善的方向;
(3)有助于理解的相关的题目
优先级:做题进度>学习&总结>默写回顾>做题数量
题目回顾
1.二叉树的最大深度
题目链接:104. 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-depth-of-binary-tree
思路:只能将二叉树所以节点都遍历,才能确定其最大深度.
1.DFS深度优先遍历-递归-三步曲
1.递归函数的类型值and返回值:以原函数为递归函数
2.单层递归逻辑:
index++,如何保证index能够迭代?使用公共变量;- 依次递归左右节点,并赋值于leftDepth,rightDepth;
- 返回值比较
result、leftDepth,rightDepth中最大的,再加1。
3.终止条件:当前节点不为空
int result = 0;
public int maxDepth(TreeNode root) {
// 如何找到最大深度,深度优先遍历-递归-public记录最大层数
// 递归函数的类型值和返回值
findMaxDepth(root,0);
return result;
}
public void findMaxDepth(TreeNode node,int index){
if(node == null){
index--;
return;
}
index++;
if(index > result){
result = index;
}
findMaxDepth(node.left,index);
findMaxDepth(node.right,index);
}
参考答案:
class solution {
/**
* 递归法
*/
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth, rightDepth) + 1;
}
}
思考:
想模拟递归过程,模拟着就想不通了,难道递归也要画图比划会比较清晰?
我的递归函数构建的类型值中会多添加int index标记变量,但看参考答案都没有添加,这样添加int合适吗?添加index的目的是便于记录和比较大小。
昨日实现的代码 :
class Solution {
public int result = 0;
public int maxDepth(TreeNode root) {
// 如何找到最大深度,深度优先遍历-递归-public记录最大层数
// 递归函数的类型值和返回值
// findMaxDepth(root,0);
// 使用层序遍历-迭代-队列ArrayDeque
if(root == null){
return 0;
}
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
while(!deque.isEmpty()){ //从根遍历到叶子节点0--i--n
int len = deque.size();
result++;
while(len-- > 0){ //将第i层全部遍历
TreeNode tNode = deque.pop();
if(tNode.left != null){
deque.offer(tNode.left);
}
if(tNode.right != null){
deque.offer(tNode.right);
}
}
}
return result;
}
public void findMaxDepth(TreeNode node,int index){
if(node == null){
index--;
return;
}
index++;
if(index > result){
result = index;
}
findMaxDepth(node.left,index);
findMaxDepth(node.right,index);
}
}
2.BFS广度优先遍历-层序遍历-迭代+队列Deque
思路:
层序遍历中外层while的循环次数就是二叉树的最大深度
层序遍历中内层while循环次数是第i层遍历的节点数
deque.offer(root);
int depth++
while(!deque.isEmpty())
- depth++;
- int len = deque.size()
- while(len-- > 0)
- TreeNode tNode = deque.poll();
参考来源:代码随想录二叉树的最大深度
2.二叉树的最小深度
题目链接:111. 二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
思路:最小深度与最大深度的区别在于其需要额外判断左右子节点是否为空
1.BFS广度优先遍历-层序遍历-迭代+队列Deque
思路:
层序遍历中外层while的循环次数就是二叉树的最大深度
层序遍历中内层while循环次数是第i层遍历的节点数,所以只需在内层增加判断左右子节点是否为空,若为空则找到最小深度。
// 13min
class Solution {
public int result = Integer.MAX_VALUE;
public int minDepth(TreeNode root) {
if(root == null){
return 0;
}
// DFS深度遍历优先-递归
findMinDepth(root,0);
return result;
// BFS广度优先遍历-迭代-队列
// Deque<TreeNode> deque = new LinkedList<>();
// deque.offer(root);
// int index = 0;
// while(!deque.isEmpty()){
// int len = deque.size();
// index++;
// while(len-- > 0){
// TreeNode tNode = deque.poll();
// if(tNode.left == null && tNode.right == null){
// return index;
// }
// if(tNode.left != null){
// deque.offer(tNode.left);
// }
// if(tNode.right != null){
// deque.offer(tNode.right);
// }
// }
// }
// return index;
// 参考答案递归
}
public void findMinDepth(TreeNode node,int index){
if(node == null){
index--;
return;
}
index++;
if(node.left == null && node.right == null && result > index){
result = index;
return;
}
findMinDepth(node.left,index);
findMinDepth(node.right,index);
}
}
2.DFS深度优先遍历-递归-三部曲
class Solution {
/**
* 递归法,相比求MaxDepth要复杂点
* 因为最小深度是从根节点到最近**叶子节点**的最短路径上的节点数量
*/
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = minDepth(root.left);
int rightDepth = minDepth(root.right);
if (root.left == null) {
return rightDepth + 1;
}
if (root.right == null) {
return leftDepth + 1;
}
// 左右结点都不为null
return Math.min(leftDepth, rightDepth) + 1;
}
}
思考:
- 感觉难时,就忘记使用递归三步曲去做,而只是没有方向的思考如何实现递归。
- 撰写单层递归逻辑要思考可能出现的错误结果,并写相关逻辑去避开。
参考链接:代码随想录二叉树的最小深度
3.完全二叉树的节点个数
题目链接:222. 完全二叉树的节点个数
给你一棵 完全二叉树 的根节点
root
,求出该树的节点个数。
思路:
完全二叉树的特性是前n-1层是满二叉树,即前n-1层的节点个数为2^(n-1)-1;
完全二叉树最后一层是从左到右增加的节点数,即最后一层最左边一定存在节点。
首先,计算出层数。
TreeNode node = root; int depth = 0;
while循环:判断node不为空,则node = node.left;depth++;
其次,计算出最后一层的节点数即可求出总长度。
DFS深度优先遍历-递归+判断(记录最后一层节点数):当左右子节点为空,则index++;
BFS广度优先遍历-迭代+队列Deque:内层while+判断(同上)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int hight = 0;
public int result = 0;
public int countNodes(TreeNode root) {
if(root == null){
return 0;
}
// DFS深度遍历
TreeNode node = root;
//计算完全二叉树的深度
while(node != null){
hight++;
node = node.left;
}
//计算最后一层的节点个数
countLastNodes(root,0);
//通过公式求解完全二叉树节点总数
result += Math.pow(2,hight-1)-1;
return result;
}
public void countLastNodes(TreeNode node,int index){
if(node == null){
index--;
return;
}
index++;
// System.out.println("index:"+index);
if(index == hight){
result++;
}
if(node.left != null){
countLastNodes(node.left,index);
}
if(node.right != null){
countLastNodes(node.right,index);
}
}
}
参考答案:
完全二叉树有两种情况:1.满二叉树 2.最后一层没有满
可通过判断最右边高度是否与最左边高度相同,若不同则为情况2,若相同则为情况1。
- 以上判断只能在其前提条件是完全二叉树时才能判断!
- 因为完全二叉树要最后一层是依次从左到右填满的
对于情况1,则直接用满二叉数公式计算节点个数:2^(n)-1
对于情况2,没看懂题解!!!
情况2参考思路:分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
class Solution {
/**
* 针对完全二叉树的解法
*
* 满二叉树的结点数为:2^depth - 1
*/
public int countNodes(TreeNode root) {
if(root == null) {
return 0;
}
int leftDepth = getDepth(root.left);
int rightDepth = getDepth(root.right);
if (leftDepth == rightDepth) {// 左子树是满二叉树
// 2^leftDepth其实是 (2^leftDepth - 1) + 1 ,左子树 + 根结点
return (1 << leftDepth) + countNodes(root.right);
} else {// 右子树是满二叉树
return (1 << rightDepth) + countNodes(root.left);
}
}
private int getDepth(TreeNode root) {
int depth = 0;
while (root != null) {
root = root.left;
depth++;
}
return depth;
}
}
总结
已经没有时间总结了哥。