1. 题目
2. 解法
解答思路
求一棵二叉树的直径,也就是树中任意两个节点之间的最长路径的长度。这条路径可能经过或不经过根节点。路径的长度用边的数量来表示。
解题思路是使用递归函数,对于每个节点,计算它的左子树和右子树的高度,
然后更新一个全局变量 max,使其为 max 和左右子树高度之和的较大值。
递归函数的返回值是当前节点的高度,也就是 1 加上左右子树高度的较大值。
具体实现
public class DiameterOfBinaryTree { public static void main(String[] args) { } int max = 0; public int diameterOfBinaryTree(TreeNode root) { dfs(root); return max; } public int dfs(TreeNode root) { if (root == null) return 0; int left = dfs(root.left); int right = dfs(root.right); max = Math.max(max, left + right); return Math.max(left, right) + 1; } }
3. 总结
树是一种非线性的数据结构,解决树的问题一般有以下两类思路:
- 先转为线性问题,然后处理。这种思路是通过遍历一棵树,将树结构转换为线性结构,如数组、链表、字符串等,然后利用线性结构的特点来解决问题。例如,通过前序遍历或后序遍历将树的节点按顺序存入数组,然后判断数组是否是回文序列,就可以判断树是否是对称的1。
- 设计有效的递归算法。这种思路是利用树的定义本身就是递归的特点,对每个节点或每个子树设计一个递归函数,来求解问题或子问题。递归函数通常需要有一个基本情况,也就是不能再分解的最小问题,和一个递归条件,也就是函数在什么情况下会继续调用自身。例如,设计一个递归函数 maxDepth(root) 来计算以 root 为根节点的树的最大深度,基本情况是当 root 为空时,返回 0;递归条件是当 root 不为空时,返回左子树的最大深度和右子树的最大深度中的较大值加 12。
这两类思路并不是互斥的,有时候也可以结合使用。
例如,要判断两棵树是否相同,
可以先用中序遍历将两棵树转换为两个数组,然后比较两个数组是否相等;
也可以用递归函数 isSameTree(p, q) 来判断以 p 和 q 为根节点的两棵子树是否相同,
基本情况是当 p 和 q 都为空时,返回 true;当 p 或 q 其中一个为空时,返回 false;当 p 和 q 都不为空但值不相等时,返回 false;
递归条件是当 p 和 q 都不为空且值相等时,返回 返回 isSameTree(p.left, q.left) && isSameTree(p.right, q.right)。