题目是LeetCode第191场周赛的第三题,链接:1466. 重新规划路线。具体描述见原题。
题目可以用BFS来解决,不过首先我们需要先建立两个邻接表toNext
和reverse
分别代表正常的邻接表和逆的邻接表(也就是边的方向反了过了)。然后套用BFS模板,先将0
号节点入队,只要队列非空就执行以下循环:
- 出队一个节点
node
,从toNext
中获得node
的邻接节点,只要未访问过则入队(同时这表明有一条路径需要进行反转),从reverse
获得指向node
的那些节点,只要未访问过,就入队(这种路径不用反转,已经是符合要求的了)。
每个节点最多出入队一次,故时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
JAVA版代码如下:
class Solution {
public int minReorder(int n, int[][] connections) {
Map<Integer, List<Integer>> toNext = new HashMap<>();
Map<Integer, List<Integer>> reverse = new HashMap<>();
for (int[] c : connections) {
if (toNext.containsKey(c[0])) {
toNext.get(c[0]).add(c[1]);
}
else {
List<Integer> item = new LinkedList<>();
item.add(c[1]);
toNext.put(c[0], item);
}
if (reverse.containsKey(c[1])) {
reverse.get(c[1]).add(c[0]);
}
else {
List<Integer> item = new LinkedList<>();
item.add(c[0]);
reverse.put(c[1], item);
}
}
Queue<Integer> queue = new LinkedList<>();
queue.offer(0);
int result = 0;
boolean[] visited = new boolean[n];
visited[0] = true;
while (!queue.isEmpty()) {
int node = queue.poll();
if (reverse.containsKey(node)) {
for (int nextNode : reverse.get(node)) {
if (!visited[nextNode]) {
visited[nextNode] = true;
queue.offer(nextNode);
}
}
}
if (toNext.containsKey(node)) {
for (int nextNode : toNext.get(node)) {
if (!visited[nextNode]) {
visited[nextNode] = true;
queue.offer(nextNode);
++result;
}
}
}
}
return result;
}
}
提交结果如下:
这里时间不咋地,因为题目的测试数据比较弱,是有排序关系的,所以看了一下有不少人利用这一点从而没有建邻接表,但是这种做法在输入数据一旦乱序的话答案就错了,所以这里先不纠结时间不咋地的问题了。
Python版代码如下:
class Solution:
def minReorder(self, n: int, connections: List[List[int]]) -> int:
toNext = collections.defaultdict(list)
reverse = collections.defaultdict(list)
visited = [False] * n
for con in connections:
toNext[con[0]].append(con[1])
reverse[con[1]].append(con[0])
queue = collections.deque()
queue.append(0)
visited[0] = True
result = 0
while len(queue) > 0:
node = queue.popleft()
for nextNode in reverse[node]:
if not visited[nextNode]:
visited[nextNode] = True
queue.append(nextNode)
for nextNode in toNext[node]:
if not visited[nextNode]:
visited[nextNode] = True
queue.append(nextNode)
result += 1
return result
提交结果如下: