题目:
Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.
Example:
Given a binary tree
1 / \ 2 3 / \ 4 5
Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3].
Note: The length of path between two nodes is represented by the number of edges between them.
又是一道不会做的easy,菜菜。
思路大概和max depth差不多,一边求max depth,一边计算以当前这个root为root的max diameter,然后和全局的max做比较。复杂度都是O(n)。
Runtime: 0 ms, faster than 100.00% of Java online submissions for Diameter of Binary Tree.
Memory Usage: 38.8 MB, less than 14.95% of Java online submissions for Diameter of Binary Tree.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int max = 0;
public int diameterOfBinaryTree(TreeNode root) {
if (root == null) {
return 0;
}
depth(root);
return max;
}
private int depth(TreeNode root) {
if (root == null) {
return 0;
}
int left = depth(root.left);
int right = depth(root.right);
max = Math.max(max, left + right);
return Math.max(left, right) + 1;
}
}
另外一种做法和我的想法挺像的,就是root的max dia是左子树的depth+右子树的depth,然后递归求左右子节点的max dia,和root做比较。但是因为有重复计算所以效率挺低的。
Runtime: 9 ms, faster than 13.15% of Java online submissions for Diameter of Binary Tree.
Memory Usage: 38.7 MB, less than 14.95% of Java online submissions for Diameter of Binary Tree.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int diameterOfBinaryTree(TreeNode root) {
if (root == null) {
return 0;
}
int rootDiameter = depth(root.left) + depth(root.right);
int left = diameterOfBinaryTree(root.left);
int right = diameterOfBinaryTree(root.right);
return Math.max(rootDiameter, Math.max(left, right));
}
private int depth(TreeNode root) {
if (root == null) {
return 0;
}
int left = depth(root.left);
int right = depth(root.right);
return Math.max(left, right) + 1;
}
}
2023.1.17:
这次还是不会写,我好菜啊。其实第二种想法更直接一些,想的有点七七八八了但还是没能凑成完整的解法。其实就是base on maxDepth,考虑递归的子问题时,有两种情况,一种是过root,一种是不过root,如果是过root那就相当于是左子树的depth + 右子树的depth的总长度,如果不过root那就是左子树的maxDia或者右子树的maxDia,然后三个比较一下取最大就完事了。reference: Java easy to understand solution - Diameter of Binary Tree - LeetCode
但因为重复计算所以效率很低,优化版就是第一种解法,记录一个全局的max,每次在求depth的时候就可以做比较了,因为这个路径不管怎么样都会有一个root,所以每次求depth的时候就更新这个max,如果当前存的max不如以这个root为root时左depth和右depth加起来的长度大,那就更新max为这个长度。(这个更新方法还需要再多思考思考,没有理解透)
迭代,需要采用post order的做法,其实和110有点像,正好也用了map来存放见过的。这里不能用queue做bfs,感觉迭代还是要看怎么迭代,并不是都可以无脑用queue的。post order的套路就是先peek,然后用if-else if-else来push左、右节点和处理当前节点。处理节点的时候也晕了,感觉思路和上面的优化版很像,我们的map里存的其实不是diameter,而是depth,所以更新节点的套路跟优化版一样,depth还是常规的Math.max(leftDepth, rightDepth) + 1,diameter则是Math.max(max, leftDepth + rightDepth)。并且注意,map存放的不是每个节点的diameter,而是它的depth。
特意造了一个不过root的case来看运行顺序:[1,2,null,4,5,6,null,7,null]
output:
4: 1
5: 1
2: 2
3: 1
1: 3
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int diameterOfBinaryTree(TreeNode root) {
int max = 0;
if (root == null) {
return 0;
}
Deque<TreeNode> stack = new ArrayDeque<>();
Map<TreeNode, Integer> map = new HashMap<>();
stack.push(root);
map.put(root, 0);
while (!stack.isEmpty()) {
TreeNode node = stack.peek();
if (node.left != null && !map.containsKey(node.left)) {
stack.push(node.left);
} else if (node.right != null && !map.containsKey(node.right)) {
stack.push(node.right);
} else {
node = stack.pop();
int left = map.getOrDefault(node.left, 0);
int right = map.getOrDefault(node.right, 0);
int depth = Math.max(left, right) + 1;
max = Math.max(max, left + right);
map.put(node, depth);
}
}
return max;
}
}