leetcode
leetcode 2851 ~ 2900
追逐游戏

追逐游戏

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 263 ms, 内存: 55.1 MB


/*
题目思路:
1. 建立图的表示:使用邻接表来表示无向图。
2. BFS策略:使用广度优先搜索来计算小力从起点到达其他点的最短距离,同时计算小扣从起点到达其他点的最短距离。
3. 最优策略:小力追小扣的过程中,小力每次尽量靠近小扣,而小扣则尽量远离小力。
4. 终止条件:一旦小力与小扣在同一位置则游戏结束,否则若小力无法追上小扣则返回 -1。
*/
import java.util.*;
import java.util.stream.Collectors;

public class ChasingGameStream {
    public int minRoundsToCatch(int[][] edges, int startA, int startB) {
        int n = edges.length;
        Map<Integer, List<Integer>> graph = Arrays.stream(edges).collect(Collectors.groupingBy(
            edge -> edge[0], Collectors.mapping(edge -> edge[1], Collectors.toList())
        ));
        graph.putAll(Arrays.stream(edges).collect(Collectors.groupingBy(
            edge -> edge[1], Collectors.mapping(edge -> edge[0], Collectors.toList())
        )));
        int[] distA = bfs(graph, startA, n);
        int[] distB = bfs(graph, startB, n);
        return IntStream.range(1, n + 1).filter(i -> distA[i] <= distB[i]).findFirst().orElse(-1);
    }

    private int[] bfs(Map<Integer, List<Integer>> graph, int start, int n) {
        int[] dist = new int[n + 1];
        Arrays.fill(dist, -1);
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(start);
        dist[start] = 0;
        while (!queue.isEmpty()) {
            int node = queue.poll();
            graph.getOrDefault(node, Collections.emptyList()).stream()
                .filter(neighbor -> dist[neighbor] == -1)
                .forEach(neighbor -> {
                    dist[neighbor] = dist[node] + 1;
                    queue.offer(neighbor);
                });
        }
        return dist;
    }
}

解释

方法:

该题解首先处理输入的边列表构建了一个无向图,并计算了每个节点的度。接着使用宽度优先搜索(BFS)来计算从起始点sta和stb到每个节点的最短距离。通过比较这两个距离数组,确定是否存在一个位置i使得小扣在小力之前到达且小力无法在下一步直接到达。如果存在这样的点,并且该点不是一个环路中的节点(即度大于1),则返回-1表示小力无法追上小扣。否则,计算小力追上小扣所需的最大距离,即为答案。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在题解中您提到构建无向图,但没有明确说明如何处理重复边或自环(如果存在的话),请问这种情况在题目中有可能发生吗?
在大多数图论问题中,尤其是在算法竞赛或在线编程平台如LeetCode中,题目通常会明确指出是否允许图中存在重复边或自环。通常,除非特别指示,我们假设输入的图不包含重复边和自环。如果题目允许这种情况发生,解题时必须对输入数据进行额外处理,比如使用集合来存储邻接点以避免重复边的影响,或者在添加边时检查是否形成自环。
🦆
题解中使用了宽度优先搜索(BFS)来找到从两个起始点到所有其他节点的最短距离。为什么选择BFS而不是DFS或其他路径查找算法?
宽度优先搜索(BFS)是确定无权图中从单一源点到其他所有点的最短路径的最优算法,因为它按层次遍历节点,确保当我们首次访问某节点时,我们已找到从起始点到该节点的最短路径。相比之下,深度优先搜索(DFS)可能会首先沿一条路径深入,不一定能直接找到最短路径。尽管其他算法如Dijkstra或Bellman-Ford也可用于找最短路径,但对于无权图来说,BFS更为简洁且效率更高。
🦆
您在代码中减少了每个节点的度并检查度为1的情况。在游戏逻辑中,节点的度数为1(即叶子节点)具有什么特殊意义?
在游戏逻辑中,度数为1的节点(即叶子节点)表示该节点仅与图中一个其他节点相连接。这在逃脱或追捕类游戏中非常关键,因为叶子节点本质上是图的边界,意味着从该节点只有一条路可走。这对策略制定非常重要,例如在追逐游戏中,如果追逐者(小力)追到一个叶子节点,且逃跑者(小扣)已经到达或即将到达那里,逃跑者的逃脱选择将非常有限。因此,叶子节点在确定追逐是否成功或是否存在潜在的逃脱路线时起着重要作用。

相关问题