文章目录
题目
标题和出处
标题:颜色交替的最短路径
难度
6 级
题目描述
要求
给定整数 n \texttt{n} n,表示有向图中的结点数,结点编号从 0 \texttt{0} 0 到 n − 1 \texttt{n} - \texttt{1} n−1。图中的每条边为红色或蓝色,可能存在自环和平行边。
给定两个数组 redEdges \texttt{redEdges} redEdges 和 blueEdges \texttt{blueEdges} blueEdges:
- redEdgesi = a i , b i \texttt{redEdgesi = a}_\\texttt{i}\\texttt{, b}\\texttt{i}\\texttt{} redEdgesi = ai, bi 表示图中有一条从结点 a i \texttt{a}\texttt{i} ai 到结点 b i \texttt{b}\texttt{i} bi 的红色有向边。
- blueEdgesj = u j , v j \texttt{blueEdgesj = u}_\\texttt{j}\\texttt{, v}\\texttt{j}\\texttt{} blueEdgesj = uj, vj 表示图中有一条从结点 u j \texttt{u}\texttt{j} uj 到结点 v j \texttt{v}\texttt{j} vj 的蓝色有向边。
返回长度为 n \texttt{n} n 的数组 answer \texttt{answer} answer,其中 answerx \texttt{answerx} answerx 是从结点 0 \texttt{0} 0 到结点 x \texttt{x} x 的红色边和蓝色边交替出现的最短路径的长度。如果不存在这样的路径,那么 answerx = -1 \texttt{answerx} = \texttt{-1} answerx=-1。
示例
示例 1:
输入: n = 3, redEdges = \[0,1,1,2], blueEdges = \[\] \texttt{n = 3, redEdges = \[0,1,1,2], blueEdges = \[\]} n = 3, redEdges = \[0,1,1,2], blueEdges = \[\]
输出: 0,1,-1 \texttt{0,1,-1} 0,1,-1
示例 2:
输入: n = 3, redEdges = \[0,1], blueEdges = \[2,1] \texttt{n = 3, redEdges = \[0,1], blueEdges = \[2,1]} n = 3, redEdges = \[0,1], blueEdges = \[2,1]
输出: 0,1,-1 \texttt{0,1,-1} 0,1,-1
数据范围
- 1 ≤ n ≤ 100 \texttt{1} \le \texttt{n} \le \texttt{100} 1≤n≤100
- 0 ≤ redEdges.length, blueEdges.length ≤ 400 \texttt{0} \le \texttt{redEdges.length, blueEdges.length} \le \texttt{400} 0≤redEdges.length, blueEdges.length≤400
- redEdgesi.length = blueEdgesi.length = 2 \texttt{redEdgesi.length} = \texttt{blueEdgesi.length} = \texttt{2} redEdgesi.length=blueEdgesi.length=2
- 0 ≤ a i , b i , u j , v j < n \texttt{0} \le \texttt{a}\texttt{i}\texttt{, b}\texttt{i}\texttt{, u}\texttt{j}\texttt{, v}\texttt{j} < \texttt{n} 0≤ai, bi, uj, vj<n
解法
思路和算法
计算最短路径,可以使用广度优先搜索实现。
由于题目中的图的表示方式是边数组,为了方便处理,需要首先将边数组转换成邻接结点列表的形式,转换后可以在 O ( 1 ) O(1) O(1) 时间获得一个结点的全部相邻结点,然后使用广度优先搜索遍历图。
由于这道题要求不同颜色边的颜色交替,因此需要分别得到红边和蓝边的邻接结点列表,广度优先搜索的状态包括结点和上次访问的边的颜色,需要记录每个结点分别以两种颜色的边作为结尾的路径长度。
初始时,结点 0 0 0 对应的红边路径和蓝边路径的长度都是 0 0 0。对于每个状态,其后续状态的结点为从当前结点出发经过一条颜色不同的路径到达的结点,其后续状态的颜色为与当前状态不同的颜色。
遍历结束后,每个结点的最短路径长度为该结点的红边路径长度和蓝边路径长度中的最小值。如果一个结点使用两种颜色的路径都不能到达,则该结点的最短路径长度为 − 1 -1 −1。
代码
java
class Solution {
public int[] shortestAlternatingPaths(int n, int[][] redEdges, int[][] blueEdges) {
final int RED = 0, BLUE = 1;
List<Integer>[][] adjacentArr = new List[n][2];
for (int i = 0; i < n; i++) {
adjacentArr[i][RED] = new ArrayList<Integer>();
adjacentArr[i][BLUE] = new ArrayList<Integer>();
}
for (int[] redEdge : redEdges) {
adjacentArr[redEdge[0]][RED].add(redEdge[1]);
}
for (int[] blueEdge : blueEdges) {
adjacentArr[blueEdge[0]][BLUE].add(blueEdge[1]);
}
int[][] distances = new int[n][2];
for (int i = 1; i < n; i++) {
Arrays.fill(distances[i], Integer.MAX_VALUE);
}
Queue<int[]> queue = new ArrayDeque<int[]>();
queue.offer(new int[]{0, RED});
queue.offer(new int[]{0, BLUE});
while (!queue.isEmpty()) {
int[] nodeColor = queue.poll();
int node = nodeColor[0], color = nodeColor[1];
int distance = distances[node][color];
int nextColor = color ^ 1;
int nextDistance = distance + 1;
List<Integer> adjacent = adjacentArr[node][nextColor];
for (int next : adjacent) {
if (nextDistance < distances[next][nextColor]) {
distances[next][nextColor] = nextDistance;
queue.offer(new int[]{next, nextColor});
}
}
}
int[] answer = new int[n];
for (int i = 0; i < n; i++) {
int distance = Math.min(distances[i][RED], distances[i][BLUE]);
answer[i] = distance != Integer.MAX_VALUE ? distance : -1;
}
return answer;
}
}
复杂度分析
-
时间复杂度: O ( n + m ) O(n + m) O(n+m),其中 n n n 是图中的结点数, m m m 是图中的边数。广度优先搜索的时间复杂度由结点数和边数决定。
-
空间复杂度: O ( n + m ) O(n + m) O(n+m),其中 n n n 是图中的结点数, m m m 是图中的边数。空间复杂度主要取决于邻接结点列表和队列,邻接结点列表需要 O ( n + m ) O(n + m) O(n+m) 的空间,队列需要 O ( n ) O(n) O(n) 的空间。