文章目录
Day 16 第六章 二叉树part03
- 今日内容:
- ● 104.二叉树的最大深度;●559.n叉树的最大深度;● 111.二叉树的最小深度;● 222.完全二叉树的节点个数
- 迭代法,大家可以直接过,二刷有精力的时候 再去掌握迭代法。
104.二叉树的最大深度 (优先掌握递归)
- 什么是深度,什么是高度,如何求深度,如何求高度,这里有关系到二叉树的遍历方式。
- 大家 要先看视频讲解,就知道以上我说的内容了,很多录友刷过这道题,但理解的还不够。
- 题目链接:
- 视频讲解: https://www.bilibili.com/video/BV1Gd4y1V75u
- 文章讲解:https://programmercarl.com/0104.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E5%A4%A7%E6%B7%B1%E5%BA%A6.html
104.后序遍历(递归+非递归)
思路
- 得到左子树深度,得到右子树深度,二者最大值加一,就是本结点深度
- 因为需要先得到左右子树深度,很显然是后序遍历典型应用
- 关于深度的定义,从根出发,离根最远的节点总边数
104.后序遍历 - 递归代码
public static int maxDepth(TreeNode root) {
if(root == null) return 0;
//下面这个判断root是叶子结点的代码可以去掉
//if(root.right == null && root.left == null) return 1;
int d1 = maxDepth(root.left);
int d2 = maxDepth(root.right);
return Integer.max(d1, d2) + 1;
}
104.后序遍历 - 非递归代码
public static int maxDepth1(TreeNode root){
TreeNode curr = root;
TreeNode pop = null;
LinkedList<TreeNode> stack = new LinkedList<>();
//代表栈的最大高度
int max = 0;
while(curr != null || !stack.isEmpty()){
if(curr != null) {
stack.push(curr);
int size = stack.size();
//max始终为栈的size的最大值
if(size > max) max = size;
curr = curr.left;
}else{
TreeNode peek = stack.peek();
if(peek.right == null || peek.right == pop){
pop = stack.pop();
}else{
curr = peek.right;
}
}
}
return max;
}
104.层序遍历
思路
通过层序遍历先判断每一层有几个元素,通过将每一层套进一个循环,计算循环次数即可
代码
public static int maxDepth2(TreeNode root){
Queue<TreeNode> queue = new LinkedList<>();
if(root != null) queue.offer(root);
int depth = 0;
while(!queue.isEmpty()){
//队列里元素的个数就是每一层元素的个数
int size = queue.size();
//不能直接把queue.size()写进for循环,因为循环的时候queue.size()会变
for(int i = 0; i < size; i++){
TreeNode poll = queue.poll();
//System.out.print(poll.val+" ");
if(poll.left != null) queue.offer(poll.left);
if(poll.right != null) queue.offer(poll.right);
}
depth ++;
//System.out.println();
}
return depth;
}
559.后序遍历 - 递归代码
public int maxDepth(Node root) {
if(root == null) return 0;
int depth = 0;
if (root.children != null){
for (Node child : root.children){
depth = Math.max(depth, maxDepth(child));
}
}
return depth + 1;
}
559.层序遍历 - 非递归代码
public int maxDepth(Node root) {
Queue<Node> queue = new LinkedList<>();
if(root != null) queue.offer(root);
int depth = 0;
while(!queue.isEmpty()){
//队列里元素的个数就是每一层元素的个数
int size = queue.size();
//不能直接把queue.size()写进for循环,因为循环的时候queue.size()会变
for(int i = 0; i < size; i++){
Node poll = queue.poll();
//System.out.print(poll.val+" ");
if(poll.children != null)
for(int j = 0; j < poll.children.size(); j ++){
queue.offer(poll.children.get(j));
}
}
depth ++;
//System.out.println();
}
return depth;
}
111.二叉树的最小深度 (优先掌握递归)
- 先看视频讲解,和最大深度 看似差不多,其实 差距还挺大,有坑。
- 题目链接:https://leetcode.cn/problems/minimum-depth-of-binary-tree/
- 视频讲解:https://www.bilibili.com/video/BV1QD4y1B7e2
- 文章讲解:https://programmercarl.com/0111.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E6%B7%B1%E5%BA%A6.html
递归
思路
如果根据求二叉树最大深度的递归代码来写的话,一条腿的二叉树最小深度就是0了,不符合题意
所以只需要对单条腿的二叉树进行条件判断,只有右子树就按左子树深度算,只有左子树就按右子树深度算
代码
public int minDepth(TreeNode root) {
if(root == null) return 0;
int d1 = minDepth(root.left);
int d2 = minDepth(root.right);
if(d1 == 0) return d2 + 1; //当左子树为null时,返回右子树深度+1
if(d2 == 0) return d1 + 1; //当右子树为null时,返回左子树深度+1
return Math.min(d1, d2) + 1; //只有左右子树都不为null时,返回最小值
}
层序遍历
思路
当遍历到叶子节点(即没有左节点也没有右节点)时,当前层数就是最小深度,其他思想与最大深度相同
代码
public static int minDepth1(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
if(root == null) return 0;
if(root != null) queue.offer(root);
int depth = 1;
while(!queue.isEmpty()){
int size = queue.size();
for(int i = 0; i < size; i ++){
TreeNode poll = queue.poll();
//找到叶子节点
if(poll.left == null && poll.right == null) return depth;
if (poll.left != null) queue.offer(poll.left);
if (poll.right != null) queue.offer(poll.right);
}
depth ++;
}
return depth;
}
222.完全二叉树的节点个数(优先掌握递归)
- 需要了解,普通二叉树 怎么求,完全二叉树又怎么求
- 题目链接:https://leetcode.cn/problems/count-complete-tree-nodes/
- 视频讲解:https://www.bilibili.com/video/BV1eW4y1B7pD
- 文章讲解:https://programmercarl.com/0222.%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%8A%82%E7%82%B9%E4%B8%AA%E6%95%B0.html
递归
思路
与求最大深度差不多
- 先得到左子树的节点数,再得到右子树的节点数,二者值相加再+节点本身1就是整个二叉树的节点数
- 因为需要先得到左右子树深度,很显然是后序遍历典型应用
代码
public static int countNodes(TreeNode root) {
if(root == null) return 0;
//先得到左子树的节点数
int c1 = countNodes(root.left);
//再得到右子树的节点数
int c2 = countNodes(root.right);
//二者值相加再+节点本身1就是整个二叉树的节点数
return c1 + c2 + 1;
}
层序遍历
public static int countNodes(TreeNode root) {
if(root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int count = 1;
while(!queue.isEmpty()){
TreeNode poll = queue.poll();
if(poll.left != null) {
queue.offer(poll.left);
count ++;
}
if(poll.right != null) {
queue.offer(poll.right);
count ++;
}
}
return count;
}