方法一
思路: 递归的计算出:从每个节点出发,向左走的最大距离和向右走的最大距离,并以每个节点的这两个值为基础进一步计算和判断整个二叉树的最大距离。。。详细步骤见代码注释。
Java代码如下:
import java.util.LinkedList;
import java.util.Queue;
class Node {
int data;
Node left;
Node right;
int maxLeftLen; // 从该节点向左走,最大距离
int maxRightLen; // 从该节点向右走,最大距离
Node(int value) {
this.data = value;
}
}
public class Solution {
// 用于保存树中的两个节点的最大距离
private int maxLen = 0;
// 使用数组建立完全二叉树
public Node buildTree(int[] datas) {
Queue<Node> nodeQueue = new LinkedList<Node>();
Node root = new Node(datas[0]);
nodeQueue.add(root);
for (int i = 1; i < datas.length; i++) {
// 取出队列中的第一个元素
Node current = nodeQueue.peek();
if (current != null) {
if (current.left == null) {
current.left = new Node(datas[i]);
nodeQueue.add(current.left);
} else {
current.right = new Node(datas[i]);
nodeQueue.add(current.right);
nodeQueue.remove();
}
}
}
return root;
}
// findMaxLen能够计算出每个节点的左右子树的最大距离,并将该值+1保存在该节点的maxLeftLen和maxRightLen中
public void findMaxLen(Node node) {
if (node == null)
return;
// 如果该节点的左子树为空,则该从该节点向左走的最长距离为0
if (node.left == null) {
node.maxLeftLen = 0;
}
// 如果该节点的右子树为空,则该从该节点向右走的最长距离为0
if (node.right == null) {
node.maxRightLen = 0;
}
// 如果该节点的左子树不为空,递归的计算出该节点的左孩子节点的maxLeftLen和maxRightLen(并更新maxLen)
if (node.left != null) {
findMaxLen(node.left);
}
// 如果该节点的右子树不为空,递归的计算出该节点的右孩子节点的maxLeftLen和maxRightLen(并更新maxLen)
if (node.right != null) {
findMaxLen(node.right);
}
// 如果该节点的左子树不为空,那么该节点的maxLeftLen等于它的左孩子节点的maxLeftLen、maxRightLen中较大的那个 + 1
if (node.left != null) {
int maxLeftLenTemp = Math.max(node.left.maxLeftLen, node.left.maxRightLen) + 1;
node.maxLeftLen = maxLeftLenTemp;
}
// 如果该节点的右子树不为空,那么该节点的maxRightLen等于它的右孩子节点的maxLeftLen、maxRightLen中较大的那个 + 1
if (node.right != null) {
int maxRightLenTemp = Math.max(node.right.maxLeftLen, node.right.maxRightLen) + 1;
node.maxRightLen = maxRightLenTemp;
}
// 到这一步,当前处理的节点的maxLeftLen和maxLeftLen已经得到了,如果它的maxLeftLen+maxRightLen值比maxLen大,就可以更新maxLen
if (maxLen < node.maxLeftLen + node.maxRightLen) {
maxLen = node.maxLeftLen + node.maxRightLen;
}
}
// 测试
public static void main(String[] args) {
int[] nums = {3,5,6,7};
Solution solution = new Solution();
Node root = solution.buildTree(nums);
solution.findMaxLen(root);
System.out.println(solution.maxLen);
}
}
方法二:
相比于方法一,方法二的代码更为简洁。
Java代码如下:
class Node {
int data;
Node left;
Node right;
Node(int value) {
this.data = value;
}
}
public class Test {
private int maxLen = 0;
// 该方法返回从root节点出发,向左或向右所能走的最远距离(该方法的返回值并非是整个树的最远距离,而是它的左子树最远距离和右子树最远距离两者中的较大值)
// maxLen用于保存整个二叉树的最远距离
public int findMaxLen(Node root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return 0;
}
int leftMaxLen = findMaxLen(root.left) + 1;
int rightMaxLen = findMaxLen(root.right) + 1;
int maxTemp = leftMaxLen + rightMaxLen;
if (maxTemp > maxLen) {
maxLen = maxTemp;
}
return leftMaxLen > rightMaxLen ? leftMaxLen : rightMaxLen;
}
// 测试
public static void main(String[] args) {
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node5 = new Node(5);
Node node6 = new Node(6);
Node node7 = new Node(7);
Node node10 = new Node(10);
Node node11 = new Node(11);
Node node9 = new Node(9);
Node node12 = new Node(12);
Node node13 = new Node(13);
Node node4 = new Node(4);
node2.left = node3;
node2.right = node4;
node3.left = node5;
node3.right = node6;
node5.left = node7;
node7.left = node10;
node10.left = node11;
node6.right = node9;
node9.right = node12;
node12.left = node13;
Test test = new Test();
// 从node2节点出发,向左走能走5,向右走能走1,因此返回二者中较大的值5.
int out = test.findMaxLen(node2);
System.out.println(out);
// maxLen返回的才是二叉树的最远距离
System.out.println(test.maxLen);
}
}