1129. Shortest-Path-with-Alternating-Colors
difficulty: Medium
section pre{ background-color: #eee; border: 1px solid #ddd; padding:10px; border-radius: 5px; }
Consider a directed graph, with nodes labelled 0, 1, ..., n-1
. In this graph, each edge is either red or blue, and there could be self-edges or parallel edges.
Each [i, j]
in red_edges
denotes a red directed edge from node i
to node j
. Similarly, each [i, j]
in blue_edges
denotes a blue directed edge from node i
to node j
.
Return an array answer
of length n
, where each answer[X]
is the length of the shortest path from node 0
to node X
such that the edge colors alternate along the path (or -1
if such a path doesn't exist).
Example 1:
Input: n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
Output: [0,1,-1]
Example 2:
Input: n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
Output: [0,1,-1]
Example 3:
Input: n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
Output: [0,-1,-1]
Example 4:
Input: n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
Output: [0,1,2]
Example 5:
Input: n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]]
Output: [0,1,1]
Constraints:
1 <= n <= 100
red_edges.length <= 400
blue_edges.length <= 400
red_edges[i].length == blue_edges[i].length == 2
0 <= red_edges[i][j], blue_edges[i][j] < n
Method One
class Solution {
public int[] shortestAlternatingPaths(int n, int[][] redEdges, int[][] blueEdges) {
// 1129
// 想法就是先选红边和先选蓝边出发,用BFS 然后 ans[] 储存最短的路径。
// tricky 的地方是 红边和蓝边要用两个 set 来标记访问过没有。也就是一个点可以被红蓝各访问一次。
int[] ans = new int[n];
Arrays.fill(ans, - 1);
Map<Integer, List<Integer> >redGraph = new HashMap<>();
Map<Integer, List<Integer> >blueGraph = new HashMap<>();
// TODO: refactor
for(int[] redEdge : redEdges ){
redGraph.putIfAbsent( redEdge[0], new ArrayList<>());
redGraph.get(redEdge[0]).add(redEdge[1]);
}
for(int[] blueEdge: blueEdges ){
blueGraph.putIfAbsent( blueEdge[0], new ArrayList<>());
blueGraph.get(blueEdge[0]).add(blueEdge[1]);
}
LinkedList<Integer> bQ= new LinkedList<>();
LinkedList<Integer> rQ= new LinkedList<>();
bQ.offer(0);
rQ.offer(0);
int level = 0;
Set<Integer> blueSet = new HashSet<>();
Set<Integer> redSet = new HashSet<>();
while(!bQ.isEmpty()){
int size = bQ.size();
while( size > 0 ){
size -= 1;
int curB = bQ.poll();
ans[curB] = ans[curB] < 0 ? level : Math.min(ans[curB], level);
Map<Integer, List<Integer> > nextBGraph = level % 2 == 0 ? blueGraph : redGraph ;
Set<Integer> nextSet = level % 2 == 0 ? blueSet : redSet;
Set<Integer> curSet = level % 2 == 1 ? blueSet : redSet;
curSet.add(curB);
for(int nextB : nextBGraph.getOrDefault(curB, new ArrayList<>()) ){
if(nextSet.contains(nextB)){
continue;
}
bQ.offer(nextB);
}
}
level += 1;
}
level = 0;
blueSet = new HashSet<>();
redSet = new HashSet<>();
while(!rQ.isEmpty()){
int size = rQ.size();
while( size > 0 ){
size -= 1;
int curR = rQ.poll();
ans[curR] = ans[curR] < 0 ? level : Math.min(ans[curR], level);
Map<Integer, List<Integer> > nextRGraph = level % 2 == 1 ? blueGraph : redGraph ;
Set<Integer> nextSet = level % 2 == 1 ? blueSet : redSet;
Set<Integer> curSet = level % 2 == 0 ? blueSet : redSet;
curSet.add(curR);
for(int nextR : nextRGraph.getOrDefault(curR, new ArrayList<>()) ){
if(nextSet.contains(nextR)){
continue;
}
rQ.offer(nextR);
}
}
level += 1;
}
return ans;
}
}
with refactor
class Solution {
private Map<Integer, List<Integer> >redGraph;
private Map<Integer, List<Integer> >blueGraph;
private int[] ans;
private final String BLUE = "blue";
private final String RED = "red";
public int[] shortestAlternatingPaths(int n, int[][] redEdges, int[][] blueEdges) {
this.ans = new int[n];
Arrays.fill(ans, -1);
this.redGraph = buildGraph(redEdges);
this.blueGraph = buildGraph(blueEdges);
bfs(BLUE);
bfs(RED);
return ans;
}
public Map<Integer, List<Integer> > buildGraph(int[][] edges){
Map<Integer, List<Integer>> graph = new HashMap<>();
for(int[] edge : edges ){
graph.putIfAbsent( edge[0], new ArrayList<>());
graph.get(edge[0]).add(edge[1]);
}
return graph;
}
public void bfs(String initColor ){
int TOGGLER = initColor.equals(BLUE) ? 0 : 1;
LinkedList<Integer> queue = new LinkedList<>();
queue.offer(0);
int level = 0;
Set<Integer> blueSet = new HashSet<>();
Set<Integer> redSet = new HashSet<>();
while(!queue.isEmpty()){
int size = queue.size();
while( size > 0 ){
size -= 1;
int cur = queue.poll();
ans[cur] = ans[cur] < 0 ? level : Math.min(ans[cur], level);
Map<Integer, List<Integer> > nextGraph = level % 2 == TOGGLER ? blueGraph : redGraph ;
Set<Integer> nextSet = level % 2 == TOGGLER ? blueSet : redSet;
Set<Integer> curSet = level % 2 != TOGGLER ? blueSet : redSet;
curSet.add(cur);
for(int next : nextGraph.getOrDefault(cur, new ArrayList<>()) ){
if(nextSet.contains(next)){
continue;
}
queue.offer(next);
}
}
level += 1;
}
}
}
Last updated
Was this helpful?