2359. 找到离给定两个节点最近的节点

题目链接

2359. 找到离给定两个节点最近的节点 - 力扣(LeetCode)

题目描述

给你一个 n 个节点的 有向图 ,节点编号为 0n - 1 ,每个节点 至多 有一条出边。

有向图用大小为 n 下标从 0 开始的数组 edges 表示,表示节点 i 有一条有向边指向 edges[i] 。如果节点 i 没有出边,那么 edges[i] == -1

同时给你两个节点 node1node2

请你返回一个从 node1node2 都能到达节点的编号,使节点 node1 和节点 node2 到这个节点的距离 较大值最小化。如果有多个答案,请返回 最小 的节点编号。如果答案不存在,返回 -1

注意 edges 可能包含环。

题目示例

示例 1 :

plain 复制代码
输入:edges = [2,2,3,-1], node1 = 0, node2 = 1
输出:2
解释:从节点 0 到节点 2 的距离为 1 ,从节点 1 到节点 2 的距离为 1 。
两个距离的较大值为 1 。我们无法得到一个比 1 更小的较大值,所以我们返回节点 2 。

示例 2 :

plain 复制代码
输入:edges = [1,2,-1], node1 = 0, node2 = 2
输出:2
解释:节点 0 到节点 2 的距离为 2 ,节点 2 到它自己的距离为 0 。
两个距离的较大值为 2 。我们无法得到一个比 2 更小的较大值,所以我们返回节点 2 。

解题思路

  1. 问题描述
    • 给定一个有向图(edges 数组表示,edges[i] 表示节点 i 指向的节点),以及两个起始节点 node1node2
    • 需要找到一个节点 i,使得:
      • node1node2 都能到达 i
      • i 是满足条件的节点中,max(dis1[i], dis2[i]) 最小的节点(即两个节点到 i 的距离的最大值最小)。
      • 如果有多个满足条件的节点,返回编号最小的那个。
  2. 核心思路
    • node1node2 分别出发,计算它们到所有其他节点的最短距离(dis1dis2)。
    • 遍历所有节点,找到同时满足以下条件的节点 i
      • dis1[i]dis2[i] 均不为 n(表示两个节点都能到达 i)。
      • max(dis1[i], dis2[i]) 最小。
    • 如果存在多个满足条件的节点,选择编号最小的那个。
  3. 关键点
    • 使用 calcDis 方法计算从某个节点出发的最短距离,利用贪心遍历(类似 BFS 的思想)。
    • 初始化距离为 n(表示无法到达),遍历时更新可达节点的距离。
    • 最终比较所有节点的 max(dis1[i], dis2[i]),选择最小值。

题解代码

java 复制代码
class Solution {
    // 主方法:找到两个节点都能到达的最近交汇节点
    public int closestMeetingNode(int[] edges, int node1, int node2) {
        // 计算从 node1 出发到所有节点的最短距离
        int[] dis1 = calcDis(edges, node1);
        // 计算从 node2 出发到所有节点的最短距离
        int[] dis2 = calcDis(edges, node2);

        int n = edges.length;
        int minDis = n; // 初始最小距离设为最大值(n 表示无法到达)
        int ans = -1;    // 初始答案为 -1(表示无解)
        // 遍历所有节点,寻找满足条件的交汇节点
        for (int i = 0; i < n; i++) {
            // 当前节点的最大距离(即两个节点到该节点的距离的较大值)
            int d = Math.max(dis1[i], dis2[i]);
            // 如果当前节点的最大距离更小,则更新答案
            if (d < minDis) {
                minDis = d;
                ans = i;
            }
        }
        return ans;
    }

    // 辅助方法:计算从节点 x 出发到所有其他节点的最短距离
    private int[] calcDis(int[] edges, int x) {
        int n = edges.length;
        int[] dis = new int[n];
        Arrays.fill(dis, n); // 初始化所有距离为 n(表示无法到达或尚未访问)
        // 从 x 出发,沿着边遍历,直到无路可走(x=-1)或重复访问节点(dis[x]<n)
        for (int d = 0; x >= 0 && dis[x] == n; x = edges[x]) {
            dis[x] = d++; // 记录当前节点的距离,并递增距离
        }
        return dis;
    }
}

复杂度分析

  1. 时间复杂度
    • calcDis 方法:
      • 遍历所有节点最多一次(因为一旦访问过就会跳过),时间复杂度为 O(n)。
    • 主方法 closestMeetingNode
      • 调用两次 calcDis,时间复杂度为 O(n)。
      • 遍历所有节点比较距离,时间复杂度为 O(n)。
    • 总时间复杂度:O(n)。
  2. 空间复杂度
    • 需要存储 dis1dis2 两个距离数组,大小为 O(n)。
    • 总空间复杂度:O(n)。
相关推荐
澈2071 小时前
哈希表:O(1)查找的终极指南
算法·哈希算法·散列表
幻奏岚音1 小时前
AI模型用户画像分析_new
人工智能·算法·计算机视觉·数据挖掘
阿Y加油吧1 小时前
二刷动态规划经典题:从打家劫舍到完全平方数,Java 实现复盘与优化
leetcode
阿Y加油吧2 小时前
二刷 LeetCode:爬楼梯与杨辉三角,Java 实现复盘
java·算法·leetcode
落羽的落羽2 小时前
【项目】C++从零实现JsonRpc框架——项目引入
linux·服务器·开发语言·c++·人工智能·算法·机器学习
凌波粒2 小时前
LeetCode--101. 对称二叉树(二叉树)
算法·leetcode·职场和发展
不知名的忻2 小时前
堆排序(Java)
java·数据结构·算法·排序算法
_深海凉_2 小时前
LeetCode热题100-二叉树的最大深度
算法·leetcode·职场和发展
智者知已应修善业2 小时前
【51单片机独立按键和定时器中断的疑惑验证】2023-11-2
c++·经验分享·笔记·算法·51单片机