树是天生的适合递归的数据结构,很多树的问题用递归都可以非常漂亮的解决,而迭代往往比较复杂。熟练使用递归解决下面的二十多个二叉树问题,就能更进一步掌握递归。
普通二叉树
104.二叉树的最大深度
子问题:左右子树中较高的高度作为当前树的高度
public class Solution {
public int maxDepth(TreeNode root) {
return root == null ? 0 : Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
}
111.二叉树的最小深度
与二叉树的最大深度有所不同,如果子树为空,最小深度不为1,因为深度定义是到叶子节点的,所以需要处理子树为空的情况
public class Solution {
public int minDepth(TreeNode root) {
//空树返回0
if (root == null) return 0;
//一边树为空返回非空树高度+1
else if (root.left == null && root.right != null) return minDepth(root.right) + 1;
else if (root.left != null && root.right == null) return minDepth(root.left) + 1;
//子树均为空或均不为空返回子树最小高度+1
else return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
}
}
110.平衡二叉树
自顶向下
子问题:当前树的左右子树高度差小于2,且左右子树都是平衡二叉树
public class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
//如果左右节点高度差小于1,且左右节点都是满足平衡的
return Math.abs(maxDepth(root.left) - maxDepth(root.right)) < 2
&& isBalanced(root.left)
&& isBalanced(root.right);
}
private int maxDepth(TreeNode node) {
return node == null ? 0 : Math.max(maxDepth(node.left), maxDepth(node.right)) + 1;
}
}
自底向上
子问题:获取当前树的左右子树的高度,如果左右子树高度差大于1,设置全局的返回值为false,然后返回树的高度
因为压栈到叶子节点才开始返回,所以是自底向上的,省去了多次获取树的高度
public class Solution {
private boolean res = true;
public boolean isBalanced(TreeNode root) {
maxDepth(root);
return res;
}
private int maxDepth(TreeNode root) {
if (root == null) return 0;
//获取左右子树高度
int left = maxDepth(root.left);
int right = maxDepth(root.right);
//如果发现不是平衡的了就设置为false;
if (Math.abs(left - right) > 1) res = false;
//返回树的高度
return Math.max(left, right) + 1;
}
}
543.二叉树的直径(两节点最大路径)
题意解释:
在二叉树中两个节点可以构成的最长路径
可以不通过根节点的情况
子问题:计算每棵子树的左右子树高度之和,最大值就是整棵树的最大值
和自底向上的求二叉树的高度的代码一致,只是每次获取左右子树高度后计算一个当前最大左右子树和
public class Solution {
private int max = 0;
public int diameterOfBinaryTree(TreeNode root) {
dfs(root);
return max;
}
private int dfs(TreeNode root) {
if (root == null) return 0;
//获取左右子树的高度
int lefth = dfs(root.left);
int righth = dfs(root.right);
//获取左右子树和的最大值
max = Math.max(max, lefth + righth);
//返回树的高度
return Math.max(lefth, righth) + 1;
}
}
687.最长同值路径
思路同上一个题两节点最大路径,自底向上
子问题:求和当前值相等的左右子树的长度的和
public class Solution {
private int path = 0;
public int longestUnivaluePath(TreeNode root) {
dfs(root);
return path;
}
private int dfs(TreeNode root) {
if (root == null) return 0;
//和左子树值相同的串的长度
int left = dfs(root.left);
//和右子树值相同的串的长度
int right = dfs(root.right);
//和当前值相同的左子树长度
int leftPath = root.left != null && root.val == root.left.val ? left + 1 : 0;
//和当前值相同的右子树长度
int rightPath = root.right != null && root.val == root.right.val ? right + 1 : 0;
//比较当前节点的路径更新最长路径
path = Math.max(path, leftPath + rightPath);
//返回当前节点的最长串长度
return Math.max(leftPath, rightPath)