目录
222.完全二叉树的节点个数
题目
代码(层序迭代)
代码(后序递归)
代码(满二次树递归)
总结
110.平衡二叉树
题目
代码(后序递归)
代码(层序迭代)
代码(前序迭代)
总结
222.完全二叉树的节点个数
题目
给你一棵 完全二叉树 的根节点 root
,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~ 2h
个节点。
示例 1:
输入:root = [1,2,3,4,5,6] 输出:6
代码(层序迭代)
class Solution {public int countNodes(TreeNode root) {//用层序迭代递归计算int size = 0; //初始大小为0Queue<TreeNode> que = new ArrayDeque<>();if(root == null){return 0;}que.offer(root);while(!que.isEmpty()){int len = que.size(); //获取当前层的节点个数size += len; //更新size//当前层节点一个个出队while(len-- > 0){TreeNode cur = que.poll();//处理左右孩子,进队if(cur.left != null){que.offer(cur.left);}if(cur.right != null){que.offer(cur.right);}}}return size;}
}
代码(后序递归)
class Solution {public int countNodes(TreeNode root) {//用后序递归遍历计算//终止条件if(root == null){return 0;}//单层逻辑int left = countNodes(root.left); //计算左子树节点数量(左)int right = countNodes(root.right); //计算右子树节点数量(右)int result = left + right + 1; //中return result;}
}
代码(满二次树递归最难理解)
class Solution {//用完全二叉树的性质递归计算,时间复杂度小于o(n)//核心原理是如果是满二叉树,左右侧深度一样,可以2^depth-1直接计算,不用全部遍历public int countNodes(TreeNode root) {//终止条件1if(root == null){return 0;}//终止条件2,是满二叉树,可以直接根据深度计算节点数TreeNode left = root.left;TreeNode right = root.right;int leftdepth = 0;int rightdepth = 0;//左孩子一直往左下走,计算左下深度while(left != null){left = left.left;leftdepth++;}//右孩子一直往右下走,计算右下深度while(right != null){right = right.right;rightdepth++;}//如果左右深度一样,说明是满二叉树,直接计算返回if(leftdepth == rightdepth){//按注释计算2^depth-1 力扣上不知道为什么通不过//return ((int)Math.pow(2,leftdepth) - 1);return (2 << leftdepth) - 1;}//单层逻辑int l = countNodes(root.left); //计算左孩子节点数(左)int r = countNodes(root.right); //计算右孩子节点数(右)int result = l + r + 1; //中return result;}
}
总结
层序迭代和后序递归的核心逻辑很简单,就是用普通的遍历二叉树的方法,一边遍历一边计算节点数,即在原先的遍历代码中加上计算节点数的代码即可。时间复杂度是o(n)。
满二叉树递归的核心逻辑,利用了满二叉树的性质,如果一个子树的满二叉树,从根节点往左和往右的最大深度是一样的。因此我们通过前序递归遍历二叉树,如果当前节点时满二叉树(终止条件),就可以直接计算节点数是2^depth-1,不用继续遍历其孩子节点。如果不是满二叉树(单层逻辑),就继续前序遍历下去,不是满二叉树的节点数=左子树节点+右子树节点+1。时间复杂度<=o(n)。
110.平衡二叉树
题目
给定一个二叉树,判断它是否是平衡二叉树
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:true
代码(后序递归最难理解)
class Solution {//后序递归判断public boolean isBalanced(TreeNode root) {int result = postOrder(root);if(result == -1){return false;}else{return true;}}//后序遍历,判断每个节点是否满足高度差<=1//返回值int有两层意思:如果=-1代表当前节点不平衡,如果不是-1,代表当前节点的高度public int postOrder(TreeNode root){//终止条件1if(root == null){return 0;}//计算当前节点的左右孩子高度int leftheight = postOrder(root.left); //左子树高度int rightheight = postOrder(root.right); //右子树高度//终止条件2,左子树不平衡if(leftheight == -1){return -1;}//终止条件3,右子树不平衡if(rightheight == -1){return -1;}//终止条件4,左右子树高度差大于1if(Math.abs(leftheight - rightheight) > 1){return -1;}//单层循环//如果该节点满足平衡二叉条件,计算该节点的高度,继续递归判断int result = 1 + Math.max(leftheight,rightheight);return result;}
}
代码(层序迭代)
class Solution {//层序迭代判断,核心逻辑是层序遍历每个节点,判断是否满足平衡条件public boolean isBalanced(TreeNode root) {//层序遍历节点,逐个判断该节点是否满足高度差<=1Queue<TreeNode> que = new ArrayDeque<>();if(root == null){return true;}que.offer(root);while(!que.isEmpty()){int size = que.size();//处理当前层的所有节点while(size-- > 0){TreeNode cur = que.poll();//计算cur的左右孩子的高度int leftheight = getheight(cur.left);int rightheight = getheight(cur.right);//如果高度差>1,不满足平衡直接returnif(Math.abs(leftheight - rightheight) > 1){return false;}if(cur.left != null){que.offer(cur.left);}if(cur.right != null){que.offer(cur.right);}}}return true;}//计算cur节点的高度public int getheight(TreeNode cur){//终止条件if(cur == null){return 0;}//单层逻辑int left = getheight(cur.left);int right = getheight(cur.right);return 1 + Math.max(left,right);}
}
代码(前序迭代)
class Solution {public boolean isBalanced(TreeNode root) {Stack<TreeNode> stack = new Stack<>();if(root == null){return true;}//前序迭代遍历每一个节点,并判断该节点是否平衡stack.push(root);while(!stack.isEmpty()){TreeNode cur = stack.pop();//计算当前cur节点的左右高度int leftheight = getheight(cur.left);int rightheight = getheight(cur.right);//如果cur不平衡,直接返回falseif(Math.abs(leftheight - rightheight) > 1){return false;}if(cur.right != null){stack.push(cur.right);}if(cur.left != null){stack.push(cur.left);}}//遍历完全部节点,都满足平衡,就返回truereturn true;}//计算cur节点的高度public int getheight(TreeNode cur){//终止条件if(cur == null){return 0;}//单层逻辑int left = getheight(cur.left);int right = getheight(cur.right);return 1 + Math.max(left,right);}
}
总结
迭代法的逻辑很简单,就是用前序、层序遍历每一个节点时,同时计算当前节点的左右孩子高度,判断当前节点的高度差是否满足平衡,如果不满足,直接返回false,如果当前节点满足,再迭代判断后面的节点。最后,如果所有节点遍历完,都没有返回false,说明二叉树的每一个节点都满足平衡条件,就返回true。
递归法,核心逻辑是一边后序递归二叉树,一边计算当前节点的左右孩子高度,判断当前遍历节点是否满足平衡,如果不满足平衡就返回-1,如果满足平衡就计算当前节点的高度。
递归法有四个终止条件,一是节点为null,返回0。二是节点的左右高度差>1,返回-1。还有两种情况千万不能漏,如果该节点的左孩子or右孩子的返回值=-1,说明其左孩子or右孩子已经不平衡了,直接返回-1。