首页 > 试题广场 >

Tree III

[编程题]Tree III
  • 热度指数:85 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 128M,其他语言256M
  • 算法知识视频讲解
给出一棵有n个节点的节点标号为1~n的有根树(根为第一个节点,并给出从第2个节点到第n个节点的父结点),请你求解它的“第二直径”的长度,即树上任意两点距离非严格的第二长距离为多少(也就是说,如果存在两条不同的,长度均为max的路径,则返回max)。
树:一张有n个节点,n-1条边的无向连通图。
示例1

输入

[1,2,3,4]

输出

3

说明

树构成了一条1-2-3-4-5的链,不难发现“第二直径”长度为3,其中1到4、2到5均满足要求。
示例2

输入

[1,1,1,1]

输出

2

说明

树构成了一朵以1为中心的花,不难发现“第二直径”长度为2(当然此时的直径也为2)。

备注:
数据满足:
对于某些容易爆栈的语言,我们强烈建议你使用bfs而不是dfs


class Solution {
public:
    /* 使用邻接表来表示每一个节点的所有子节点。 */
    vector<vector<int>> graph;
    
    /* height用来存储当前节点向下的最高距离和第二高的距离。 */
    vector<pair<int, int>> height;
    
    /* max1和max2分别表示整体的第一长距离和第二长距离。 */
    int max1, max2;

    int tree3(vector<int>& e) {
        // write code here
        int n = e.size() + 1, i, j, k;
        graph.resize(n + 1);
        
        /* 初始化所有数据。 */
        for(i = 0; i < n - 1; i++) graph[e[i]].push_back(i + 2);
        height.resize(n + 1, {0, 0});
        max1 = 0, max2 = 0;
        
        /* 从root开始进行dfs。 */
        dfs(1);
        return max2;
    }

    void dfs(int start) {
        /* 没有子节点就记录为(1, 0) */
        if(graph[start].size() == 0) height[start] = make_pair(1, 0);
        else {
            /* h1和h2表示当前节点向下的最高距离和第二高的距离。 */
            int h1 = 0, h2 = 0, i, j;
            /* 有子节点,对所有子节点进行dfs。 */
            for(i = 0; i < graph[start].size(); i++) {
                dfs(graph[start][i]);
                if(height[graph[start][i]].first + 1 > h1) {
                    h2 = h1;
                    h1 = height[graph[start][i]].first + 1;
                }
                else if(height[graph[start][i]].first + 1 > h2) h2 = height[graph[start][i]].first + 1;
                if(height[graph[start][i]].second + 1 > h2) h2 = height[graph[start][i]].second + 1;
            }
            /* 如果只有一个子节点,那么就直接更新max1和max2。 */
            if(graph[start].size() == 1) {
                int t1 = height[graph[start][0]].first;
                int t2 = height[graph[start][0]].second;
                if(t1 > max1) {
                    max2 = max1;
                    max1 = t1;
                }
                else if(t1 > max2) max2 = t1;
                if(t2 > max2) max2 = t2;
            }
            /* 如果有两个及以上的子节点,就两层遍历更新max1和max2。 */
            for(i = 0; i < graph[start].size() - 1; i++) {
                for(j = i + 1; j < graph[start].size(); j++) {
                    int tmp1 = height[graph[start][i]].first + height[graph[start][j]].first;
                    int tmp2 = max(height[graph[start][i]].first + height[graph[start][j]].second, height[graph[start][j]].first + height[graph[start][i]].second);
                    if(tmp1 > max1) {
                        max2 = max1;
                        max1 = tmp1;
                    }
                    else if(tmp1 > max2) max2 = tmp1;
                    if(tmp2 > max2) max2 = tmp2;
                }
            }
            /* 更新当前节点的height。 */
            height[start] = make_pair(h1, max(h1 - 1, h2));
        }
    }
};

发表于 2021-03-23 20:42:56 回复(0)