一、倒置层序遍历
题目:
/** * 给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) * <p> * 例如: * 给定二叉树 [3,9,20,null,null,15,7], * 3 * / \ * 9 20 * / \ * 15 7 * 返回其自底向上的层次遍历为: * [ * [15,7], * [9,20], * [3] * ] */
树的层序遍历有两种,一种用队列实现,一种用递归实现。
队列:使用while循环,只要队列不为空就循环。不断的取节点,按照左右节点顺序放入队列
递归:先递归算出树的高度,使用for循环,传入层次,递归找到该层
队列的时间复杂度比较低,但占用空间大,递归的时间复杂度高很多,但是占用空间小
这道题与层序遍历的区别就是倒置,可以使用list.add(0,item)来实现,或者栈
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public List<List<Integer>> method1(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
int size = q.size();
List<Integer> tmp = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode node = q.poll();
tmp.add(node.val);
if (node.left != null) q.offer(node.left);
if (node.right != null) q.offer(node.right);
}
result.add(0, tmp);
}
return result;
}
二、树的最小深度
题目:
/** * 给定一个二叉树,找出其最小深度。 * 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 * 说明: 叶子节点是指没有子节点的节点。 * 示例: * 给定二叉树 [3,9,20,null,null,15,7], * 3 * / \ * 9 20 * / \ * 15 7 * 返回它的最小深度 2. */
如果你会求树的最大深度,那么这道题就是它的翻版
直接使用递归,哪边深度小算哪边的
树的节点
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public static int method1(TreeNode root) {
if (root==null){
return 0;
}
if (root.left==null){
return method1(root.right)+1;
}
if (root.right==null){
return method1(root.left)+1;
}
int left=method1(root.left)+1;
int right=method1(root.right)+1;
return left>right?right:left;
}
优化一下代码
public static int method2(TreeNode root){
if(root==null) return 0;
int l =method2(root.left);
int r =method2(root.right);
if(l==0 ||r==0)
return l+r+1;//在左子树和右子树中仅有一个存在的情况下,返回存在的值(即其中一颗树的minDepth为0)
return Math.min(l,r)+1;//在左子树和右子树都存在的情况下返回两者最小值
}
三、指定的路径和
题目:
/** * 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。 * 说明: 叶子节点是指没有子节点的节点。 * 示例: * 给定如下二叉树,以及目标和 sum = 22, * 5 * / \ * 4 8 * / / \ * 11 13 4 * / \ \ * 7 2 1 * 返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。 * */
树的结构
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
其实这就是一道树的遍历问题,可以使用前序遍历,中序遍历,后序遍历都可以,递归减去当前节点值,如果正好减到零且该节点是叶子节点,那么就返回true。不同路径返回值使用或逻辑运算符,只要找到一条即可
这里只演示一种前序遍历
public boolean method1(TreeNode root, int sum) {
if (root==null){
return false;
}
int value=sum-root.val;
if (value==0&&root.left==null&&root.right==null){
return true;
}
return method1(root.left,value)||method1(root.right,value);
}
四、高度平衡的二叉树
题目:
/** * 给定一个二叉树,判断它是否是高度平衡的二叉树。 * 本题中,一棵高度平衡二叉树定义为: * 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 * 示例 1: * 给定二叉树 [3,9,20,null,null,15,7] * 3 * / \ * 9 20 * / \ * 15 7 * 返回 true 。 * 示例 2: * 给定二叉树 [1,2,2,3,3,null,null,4,4] * 1 * / \ * 2 2 * / \ * 3 3 * / \ * 4 4 * 返回 false 。 */
树的结构
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
第一种思路:遍历每一层,只要左右子树高度相差大于1就返回false,缺点就是递归套递归,时间复杂度高
public static boolean method1(TreeNode root) {
if (root==null)return true;
int cha=Math.abs(getDepth(root.left)-getDepth(root.right));
System.out.println(cha);
if (cha>1){
return false;
}else {
return method1(root.left)&&method1(root.right);
}
}
public static int getDepth(TreeNode root){
if (root==null)return 0;
int left=getDepth(root.left)+1;
int right=getDepth(root.right)+1;
return Math.max(left,right);
}
改进思路:倒序遍历整棵树,减少了递归,复杂度降低很多
public static boolean method2(TreeNode root){
return heightOf(root) != null;
}
private static Integer heightOf(TreeNode node) {
if (node == null) return 0;
Integer left = heightOf(node.left);
Integer right = heightOf(node.right);
return left == null || right == null || Math.abs(left - right) > 1 ? null : 1 + Math.max(left, right);
}