【数据结构】树的直径

文章目录

  • 1. 定义
  • 2. 求法
    • 2.1. 一次深度优先搜索
      • 2.1.1. 二叉树的直径
        • 2.1.1.1. [题目](https://leetcode.com/problems/diameter-of-binary-tree/)
        • 2.1.1.2. [题解](https://leetcode-cn.com/problems/diameter-of-binary-tree/solution/er-cha-shu-de-zhi-jing-by-leetcode/)
          • 2.1.1.2.1. Python代码
          • 2.1.1.2.2. Java代码
          • 2.1.1.2.3. 复杂度分析
      • 2.1.2. 推广
    • 2.2. [两次BFS(或两次DFS)](https://blog.csdn.net/forever_dreams/article/details/81051578)
      • 2.2.1. 方法
      • 2.2.2. 证明

1. 定义

  • 结点的度:一个结点含有的子结点的个数;
    The degree of a given node is its number of children.
  • 叶结点:又称终端结点,指度为0的结点,即该节点没有子节点;
    Leaf / External node (not common): A node with no children. A leaf is necessarily degree zero.
  • Edge: The connection between one node and another.
    :两点之间的连接。一般地,这两点之间的连接为连线,且两点间的关系为父子关系。
  • Path: A sequence of nodes and edges connecting a node with a descendant.
    路径:两点之间的所有点和边所形成的序列。
  • Distance: The number of edges along the shortest path between two nodes.
    距离:两点间最短路径上边的数量。
  • 树的直径:树上距离最远的两点间的距离。一般地,距离最远的这两点均为叶节点。特殊地,一棵仅含两个点的树,此时的直径为根节点与另一个节点的距离,直径为1;仅含一个根节点的树的直径为0。
    The diameter of a 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.

2. 求法

2.1. 一次深度优先搜索

2.1.1. 二叉树的直径

2.1.1.1. 题目

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.

2.1.1.2. 题解

任意一条路径可以被写成两个箭头(不同方向),每个箭头代表一条从某些点向下遍历到孩子节点的路径。
假设我们知道对于每个节点最长箭头距离分别为 L, R,那么最优路径经过L+R+1个节点。
按照常用方法计算一个节点的深度:max(depth of node.left, depth of node.right) + 1。在计算的同时,经过这个节点的路径长度为 1 + (depth of node.left) + (depth of node.right) 。搜索每个节点并记录这些路径经过的点数最大值,期望长度是结果 - 1。

2.1.1.2.1. Python代码
class Solution(object):
    def diameterOfBinaryTree(self, root):
        self.ans = 1
        def depth(node):
            if not node: return 0
            L = depth(node.left)
            R = depth(node.right)
            self.ans = max(self.ans, L+R+1)
            return max(L, R) + 1

        depth(root)
        return self.ans - 1
2.1.1.2.2. Java代码
class Solution {
    int ans;
    public int diameterOfBinaryTree(TreeNode root) {
        ans = 1;
        depth(root);
        return ans - 1;
    }
    public int depth(TreeNode node) {
        if (node == null) return 0;
        int L = depth(node.left);
        int R = depth(node.right);
        ans = Math.max(ans, L+R+1);
        return Math.max(L, R) + 1;
    }
}
2.1.1.2.3. 复杂度分析
  • 时间复杂度:O(N),每个节点只访问一次。
  • 空间复杂度:O(N),深度优先搜索的栈开销。

2.1.2. 推广

求一般树时原理与二叉树的求法一样。

2.2. 两次BFS(或两次DFS)

2.2.1. 方法

先从任意一点P出发,找离它最远的点Q,再从点Q出发,找离它最远的点W,W到Q的距离就是树的直径。

2.2.2. 证明

也可参考:

  • https://blog.csdn.net/idealistic/article/details/52096362
  • https://www.cnblogs.com/ymzjj/p/9767526.html
  1. 若P已经在直径上,根据树的直径的定义可知Q也在直径上且为直径的一个端点
  2. 若P不在直径上,我们用反证法,假设此时WQ不是直径,AB是直径
    —>若AB与PQ有交点C,由于P到Q最远,那么PC+CQ>PC+CA,所以CQ>CA,易得CQ+CB>CA+CB,即CQ+CB>AB,与AB是直径矛盾,不成立,如下图(其中AB,PQ不一定是直线,画成直线是为了方便):
    【数据结构】树的直径_第1张图片
    —>若AB与PQ没有交点,M为AB上任意一点,N为PQ上任意一点。首先还是NP+NQ>NQ+MN+MB,同时减掉NQ,得NP>MN+MB,易知NP+MN>MB,所以NP+MN+MA>MB+MA,即NP+MN+MA>AB,与AB是直径矛盾,所以这种情况也不成立,如下图:
    【数据结构】树的直径_第2张图片

你可能感兴趣的:(数据结构)