随想录训练营Day16 | 104. 二叉树的最大深度, 559.N 叉树的最大深度,101.二叉树的最小深度, 110.平衡二叉树
标签: LeetCode闯关记
104. 二叉树的最大深度
- 递归法
class Solution {
public int maxDepth(TreeNode root) {
//求最大深度就是求根节点的高度,采用后序遍历,将得到的左右子树的高度的最大值返回给父节点,父节点的高度就是该最大值+1;
//终止条件
if(root == null){
return 0;
}
//每一次递归的操作
int leftDepth = maxDepth(root.left);//左
int rightDepth = maxDepth(root.right);//右
return Math.max(leftDepth,rightDepth) + 1;//关键:中 + 1 返回父节点的高度
}
}
- 迭代法
class Solution {
public int maxDepth(TreeNode root) {
//层序遍历,用栈来实现
Deque<TreeNode> deque = new LinkedList<>();
int depth = 0;
if (root == null) {
return depth;
}
deque.add(root);
while (!deque.isEmpty()) {
depth++;
int len = deque.size();
while (len > 0) {
TreeNode node = deque.pop();
if (node.left != null) {
deque.offer(node.left);
}
if (node.right != null) {
deque.offer(node.right);
}
len--;
}
}
return depth;
}
}
559.N 叉树的最大深度
- 层序遍历
class Solution {
public int maxDepth(Node root) {
//层序遍历
Deque<Node> deque = new LinkedList<>();
int depth = 0;
if(root == null){
return depth;
}
deque.add(root);
while (! deque.isEmpty()){
int len = deque.size();
while ((len-- > 0)){
Node node = deque.pop();
for (Node child : node.children) {
if(child != null){
deque.add(child);
}
}
}
depth++;
}
return depth;
}
}
- 迭代法+层序遍历
class Solution {
public int maxDepth(Node root) {
//后序遍历
if(root == null){
return 0;
}
int depth = 0;
//Q:这里是否需要if判断 if (root.children != null)
for (Node child : root.children) {
depth = Math.max(depth, maxDepth(child));
}//类比二叉树先遍历的:左右
return depth + 1;//类比二叉树遍历的: 中 //一定要+ 1 :理解为什么 因为子节点访问到null之后会返回0,那么返回其父节点的高度就为 0+1;
}
}
101.二叉树的最小深度
- 迭代法:层序遍历
class Solution {
//迭代法
public int minDepth(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();
if(root == null){return 0;}
deque.add(root);
int depth = 0;//用以记录深度
while (!deque.isEmpty()){
int len = deque.size();
depth++;
for (int i = 0; i < len; i++) {
TreeNode node = deque.pop();
if(node.left != null){
deque.add(node.left);
}
if(node.right != null){
deque.add(node.right);
}
if(node.left == null && node.right == null){//关键
return depth;
}
}
}
return depth;
}
}
- 递归法 + 后序遍历
class Solution {
//递归法,后序遍历
public int minDepth(TreeNode root) {
if(root == null){
return 0;
}
int leftMinDepth = minDepth(root.left);
int rightMinDepth = minDepth(root.right);
if (root.left == null){ //关键判断
return rightMinDepth + 1;
}
if(root.right == null){//关键判断
return leftMinDepth + 1;
}
// if (root.left != null && root.right != null)
return Math.min(leftMinDepth,rightMinDepth) + 1;
}
}
222.完全二叉树的节点个数
当作普通二叉树来做
- 递归法
class Solution {
//按照普通二叉树来做, 递归法
public int countNodes(TreeNode root) {
if(root == null){
return 0;
}
int leftCount = countNodes(root.left);
int rightCount = countNodes(root.right);
return (leftCount + rightCount + 1);
}
}
- 迭代法
class Solution {
//按照普通二叉树来做, 迭代法
public int countNodes(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();
if(root == null){return 0;}
deque.add(root);
int count = 0;//用以记录节点数
while (!deque.isEmpty()){
int len = deque.size();
for (int i = 0; i < len; i++) {
TreeNode node = deque.pop();
count++;
if(node.left != null){
deque.add(node.left);
}
if(node.right != null){
deque.add(node.right);
}
}
}
return count;
}
}
- 根据完全二叉树特性的递归法
- 根据完全二叉树的特性
- 思路: 利用递归找完全二叉树中的满二叉树,注意,不会陷入死循环,因为叶子节点必定是满二叉树;
- 理解这种方法的好处: 可以不遍历满二叉树的内侧节点,在数据量很大的情况下,效果很明显;
- 此方法注意: 1. 终止条件有两个,①root == null; ②找到满二叉树;
- tips: 理解递归,还是就分成三种理解,不用整理理解,很容易晕;
- 这个方法的效果的话,我认为,应该是①如果不是满二叉树,肯定遇到终止条件1,root == null, 所以自下而上记录节点数,就像遍历普通二叉树一样;②if满足终止条件2,说明找到满二叉树,则利用其特性2^k - 1, 算出节点,而不需要遍历整个满二叉树,即不需要触发终止条件1(root == null).
class Solution {
public int countNodes(TreeNode root) {
//终止条件1
if(root == null){
return 0;
}
TreeNode left = root.left;
TreeNode right = root.right;
int leftlen = 0; //细节: 理解初始为0的原因 ---联系满二叉树的节点数:2^k - 1 以及位运算: int result = 2 << 2; // 等价于 2的3次方
int rightlen = 0;
while(left != null){//关键:求左子树的深度 //Q:有没有递归的动画演示?
left = left.left;
leftlen++;
}
while(right != null){//求右子树的深度
right = right.right;
rightlen++;
}
if(rightlen == leftlen){ //终止条件2
return (2 << rightlen) - 1;// 注意(2<<1) 相当于2^2,所以leftDepth初始为0; `<<`表示在二进制中,左移并补0;
}
//后序遍历,左右中
int leftCount = countNodes(root.left);//左
int rightCount = countNodes(root.right);//右
return leftCount + rightCount + 1;//中
}
}
110.平衡二叉树
class Solution {
//思路: 高度平衡-高度-后续遍历-左右中 关键点:比较左右子树的高度,若发现有子树的高度差大于1,则一定不是平衡二叉树
public boolean isBalanced(TreeNode root) {
return getHeight(root) != -1;
}
private int getHeight(TreeNode root){
if(root == null){
return 0;
}
int leftHeight = getHeight(root.left);//左
//添加判断条件,如果左子树已经确定不是平衡二叉树了,直接终止
// Q:不是很懂为什么还要判断,不是"if(Math.abs(leftHeight - rightHeight) > 1 ){return -1;}"就能够判断不是平衡二叉树,并且终止比较了吗?
if(leftHeight == -1){
return -1;
}
int rightHeight = getHeight(root.right);//右
//添加判断条件,如果右子树已经确定不是平衡二叉树了,直接终止
if(rightHeight == -1){
return -1;
}
// 左右子树高度差大于1,return -1表示已经不是平衡树了
if(Math.abs(leftHeight - rightHeight) > 1 ){
return -1;
}else{//基于左子树的高度和右子树的高度 并加上当前父节点 返回当前父节点的高度
return Math.max(leftHeight,rightHeight) + 1;
}
}
}
发问: Q:不是很懂为什么还要判断,不是"if(Math.abs(leftHeight - rightHeight) > 1 ){return -1;}"就能够判断不是平衡二叉树,并且终止比较了吗?