LeetCode 第 304场周赛 —— T3

103 阅读3分钟

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

题目描述

       给定一个数组edges表示有向图边的情况,edges[i]=j 所表示的含义为i->j之间有一条有向边,edges[i]=-1 表示节点i没有出边。给出两个节点node1、node2,返回从节点node1、node2都能到达的节点的距离较大值最小化的节点编号。

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

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

       所要找出的是节点2和3都能到达且节点距离较大值最小化的节点编号。可以看出节点2能到达的点为2、1,3能到达的点为4、2、1。可见二者都能到达1、2,但到达节点 1 的距离为3(节点 3 到达节点 1 的距离 ),到达节点 2 的距离为2(节点 3 到达节点 2 的距离 ),因为要选择距离最小化,所以答案应为节点2。

本题值得注意的地方

  • 所给的两个节点可能为同一节点
  • 每个节点最多有一条出边
  • 图中没有自环
  • 图中有可能存在环

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

解题思路

       因为每个节点最多只有一条出边,所以可以分别对给出的两个节点分别进行查找其能够到达的节点,在查找时,同时也要记录其到该节点的距离。在找出两个节点所能到达的节点后,还要对这些节点进行比较,挑选出到达这两个节点最大距离最小的节点。

       为了方便起见,我们可以使用两个map来存储两个节点所能到达的节点及其距离。其key为节点编号,其value为距离。最后遍历每个节点,如果两个map中都有某节点的key,则该节点可由node1、node2到达,比较所有符合的节点在map1、map2中的最大值,取最大值最小的节点返回。

       当然,为了防止图中的环所引起死循环,可以对访问过的节点进行标记。

实现代码

class Solution {
public:
    int closestMeetingNode(vector<int>& edges, int node1, int node2) {
        int len = 0,nd1 = node1,nd2 = node2,ans = -1;
        // 分别用来存储node1、node2所能到达的节点及距离
        unordered_map<int,int> ndmp1,ndmp2;
        // 标记节点的访问情况
        bool st[edges.size()+1];
        // 初始化为false
        memset(st,0,sizeof st);
        // 寻找node1所能到达的节点
        while( nd2 != -1 &&!st[nd2]  ){
            st[nd2] = true;
            ndmp2[nd2] = len++;
            nd2 = edges[nd2];
        }
        // 重置st、len,寻找node2所能达到的节点
        memset(st,0,sizeof st);
        len = 0;
        while(nd1 != -1&& !st[nd1]  ){
            st[nd1] = true;
            ndmp1[nd1] = len++;
            nd1 = edges[nd1];
        }
        // 寻找node1、node2所能达到的公共节点
        for(int i = 0;i < edges.size();i++){
            // 找到到达公共节点最大距离最小的节点
            if(ndmp1.count(i)>0 && ndmp2.count(i)>0){
                if(ans != -1 && max(ndmp1[ans],ndmp2[ans]) > max(ndmp1[i],ndmp2[i])) ans = i;
                else if(ans == -1) ans = i;
            }
        }
        return ans;
    }
};