LeetCode 第 304场周赛 —— T4

126 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情

题目描述

       给定一个数组edges表示有向图边的情况,edges[i]=j 所表示的含义为i->j之间有一条有向边,edges[i]=-1 表示节点i没有出边。返回图中最长的环,如果不存在环则返回-1。

例1:输入:[2,-1,1,4,2]  输出:"-1"

解释:该图的结构如下图所示 1.png

可以看出该图不存在环,所以返回-1。

例2:输入:[3,0,4,1,6,2,5]  输出:"4"

解释:该图的结构如下图所示

2.png 可以看出该图最长的环为4。

本题值得注意的地方

  • 每个节点最多有一条出边
  • 图中没有自环

原题地址:6134. 找到离给定两个节点最近的节点

解题思路

       遍历每个未被访问过的节点,若从该节点开始顺着出边往下依次访问时能够访问到已经访问过的节点,则说明该条访问路径中存在环。

3.png        如上图所示,在访问节点0时,依次可以访问到0、3、2、4、6、5,继续向下访问节点2时可以得到节点2已经被访问,由此可知该路径中存在环,且环的长度为从第一次访问节点2开始到访问节点2失败之间的路径长度,即2、4、6、5。

       可以使用一个标记数组来标记各个节点的被访问情况。在寻找路径时将路径上的节点存储下来,方便遇到环时计算环的长度。

实现代码

class Solution {
public:
    int longestCycle(vector<int>& edges) {
        // 记录各节点的访问情况
        bool flag[edges.size()+1];
        // 初始时各节点均没被访问
        memset(flag,0,sizeof flag);
        // 记录环的大小
        int res = -1;
        for(int nd = 0;nd < edges.size();nd++) {
            // 判断该节点是否被访问过
            if(flag[nd]) continue;
            int curnd = nd;
            vector<int> cycle;
            // 将路径记录下来
            while(curnd!=-1 && !flag[curnd]) {
                flag[curnd] = true;
                cycle.push_back(curnd);
                curnd = edges[curnd];
            }
            // 判断环是否存在,存在即计算环的大小
            for(int j = 0;j < cycle.size() &&curnd!=-1;j++) {
                if(cycle[j] == curnd) {
                    int l = cycle.size() - j;
                    if(l > res) res = l;
                    break;
                }
            }
        }
        return res;
    }
};