题解 | #最长路径#

最长路径

http://www.nowcoder.com/practice/430ded6b482d4d8bbcf2eca6f20e62e3

题意理解

n个房子对应于n个结点,街道就对应于结点之间的边,构成一张连通图。找到这张图中哪两点之间边上的数值之和最大。

方法一

深度优先搜索
使用二维数组path存储路径的信息,对于每一个点,要记录它和其它结点所有路径的长度。然后以每一个点分别作为起点,都进行一次深度优先搜索,每走一步都更新一次最长路径ans,注意这里的ans不需要退回。

示意图如下,最终答案对应的路径是1-5-2-3这一条路径的长度:
图片说明

具体代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回最终结果
     * @param n int整型 城市数量
     * @param u int整型vector 
     * @param v int整型vector 
     * @param w int整型vector 
     * @return long长整型
     */
    vector<pair<int, int>> path[100000];
    long long ans=0;
    //x表示这一步的起点,pre表示上一步的起点
    void dfs(int x, int pre, long long sum) {
        for (int i=0;i<path[x].size();i++) {
            //不能往回走
            if (path[x][i].first==pre) continue;
            //不断更新ans
            ans = max(sum + path[x][i].second, ans);
            dfs(path[x][i].first, x, sum+path[x][i].second);
        }
    }


    long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& w) {
        //path每个位置记录该点与其它点存在的连边
        for (int i=0;i<n-1;i++) {
            path[u[i]].push_back({v[i],w[i]});
            path[v[i]].push_back({u[i],w[i]});
        }
        //对每个结点作为起始点进行dfs
        for (int i=1;i<=n;i++) {
            if (path[i].size()==1) {
                dfs(i,i,0);
            }
        }
        return ans;
    }
};

时间复杂度:。每一个点作为起点遍历了一遍整个点集,是的时间,n个点总共是
空间复杂度:。创建了一个二维数组来存储路径和点的信息。

方法二

对于一条路径,我们可以把它看成两条路径在同一结点处的拼接,以该点为连接点。所以,我们在递归的时候,不断更新维护每一个点的某两个子树child_i,child_j中最长路径相加得到的最大值。
同时,我们不需要考虑来时路径所在的子树child_v,因为如果以结点u为拼接点的最长路径来自于child_v和某个child_i,则这种情况会在以v为拼接点时考虑进去。

最重要的一点,在每一层的中,我们遍历当前拼接点x的path[x]之后,就已经完成了对x点所以情况的搜索,这与方法一是不一样的,方法一只是完成了以某个特定点为起点,经过x的路径的搜索。这导致我们在主程序中不需要循环调用dfs。

例如在方法一的图中,以5为例,它有4子树,以5为拼接点的最长路径可能是其中某两个子树的拼接。

具体代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 返回最终结果
     * @param n int整型 城市数量
     * @param u int整型vector 
     * @param v int整型vector 
     * @param w int整型vector 
     * @return long长整型
     */
    vector<pair<int, int>> path[100000];
    long long ans=0;
    //x表示这一步的起点,pre表示上一步的起点
    long long dfs(int x, int pre){
        long long child1 = 0;
        for(int i=0;i<path[x].size();i++){
            if(path[x][i].first != pre){
                long long child2 = dfs(path[x][i].first, x) + path[x][i].second;
                //更新ans
                ans = max(ans, child1+child2);
                //保留更长的子树中的路径
                child1 = max(child1, child2);
            }
        }
        return child1;
    }

    long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& w) {
        //path每个位置记录该点与其它点存在的连边
        for (int i=0;i<n-1;i++) {
            path[u[i]].push_back({v[i],w[i]});
            path[v[i]].push_back({u[i],w[i]});
        }
        //选择任意一个点开始
        dfs(1, 0);
        return ans;
    }
};

时间复杂度:。仅仅在递归过程中遍历了一遍所有的点,主程序中没有对dfs进行循环调用。
空间复杂度:。和方法一一样,创建了一个二维数组来存储路径和点的信息。

全部评论

相关推荐

头像
10-09 19:35
门头沟学院 Java
洛必不可达:java的竞争激烈程度是其他任何岗位的10到20倍
点赞 评论 收藏
分享
ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务