文章

1129. 颜色交替的最短路径

问题1129 颜色交替的最短路径 ★★☆☆☆

https://leetcode.cn/problems/shortest-path-with-alternating-colors/

这个题目可是费了不少的时间和精力。从解题入手点来说,大的思路并不难,比较容易想到可以通过广度优先遍历(BFS)来解决这个问题。问题的关键在于每一层BFS具体做哪些操作?这可以从循环不变量来入手。我一开始的思路是每次进入循环时,当前维护着这样两个变量:shortestPathLength[],记录的是从0节点到v节点的最短颜色交错路径长度;lastPathColor[],记录的是从0节点到v节点的最短颜色交错路径的最后一条path的颜色,可能的取值有不可达、红色、蓝色、红蓝均可等四种情况。在当前遍历中,根据当前v节点的lastPathColor,决定是继续遍历redEdges或者blueEdges或者都遍历,同时更新遍历到的节点的shortestPath和lastPathColor。直到遍历结束,根据lastPathColor确定不可达的节点并更新shortestPathLength,然后返回。整个思路看起来还挺正确吧?处理了一些细节问题以后,最终的结果是超时,出现了死循环,因为可能出现环,对于已经遍历过的节点是否要二次遍历直觉上很难处理。

最终只得参考了下官方题解,看了一下官方题解,大的思路是类似的,但有一个地方启发了我,那就是分别维护shortestPathLengthWithRedLastPath[]和shortestPathLengthWithBlueLastPath[],而不是妄图用一个lastPathColor[]来维护所有可能的状态。修改了一下代码,终于通过了,但是代码看起来有点复杂,不过相比官方题解的代码,我又觉得不如我自己写的好理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
	public int[] shortestAlternatingPaths(int n, int[][] redEdges, int[][] blueEdges) {
		int[] shortestPathLengthWithRedLastPath = new int[n];
		shortestPathLengthWithRedLastPath[0] = 0;
		for (int i = 1; i < n; i++) {
			shortestPathLengthWithRedLastPath[i] = -1;
		}

		int[] shortestPathLengthWithBlueLastPath = new int[n];
		shortestPathLengthWithBlueLastPath[0] = 0;
		for (int i = 1; i < n; i++) {
			shortestPathLengthWithBlueLastPath[i] = -1;
		}

		Queue<Integer> queue = new LinkedList<>();
		queue.offer(0);

		while (!queue.isEmpty()) {
			int v = queue.poll();

			if (shortestPathLengthWithBlueLastPath[v] != -1) {
				int length = shortestPathLengthWithBlueLastPath[v] + 1;
                for (int[] redEdge : redEdges) {
                    if (redEdge[0] == v) {
                        int next = redEdge[1];

                        if (shortestPathLengthWithRedLastPath[next] == -1) {
                            shortestPathLengthWithRedLastPath[next] = length;
                            queue.add(next);
                        } else {
                            if (length < shortestPathLengthWithRedLastPath[next]) {
                                shortestPathLengthWithRedLastPath[next] = length;
                            }
                        }
                    }
                }
			}

			if (shortestPathLengthWithRedLastPath[v] != -1) {
				int length = shortestPathLengthWithRedLastPath[v] + 1;
                for (int[] blueEdge : blueEdges) {
                    if (blueEdge[0] == v) {
                        int next = blueEdge[1];

                        if (shortestPathLengthWithBlueLastPath[next] == -1) {
                            shortestPathLengthWithBlueLastPath[next] = length;
                            queue.add(next);
                        } else {
                            if (length < shortestPathLengthWithBlueLastPath[next]) {
                                shortestPathLengthWithBlueLastPath[next] = length;
                            }
                        }
                    }
                }
			}
		}

		int[] shortestPathLength = new int[n];
		for (int i = 0; i < n; i++) {
			int withRedLastPath = shortestPathLengthWithRedLastPath[i];
			int withBlueLastPath = shortestPathLengthWithBlueLastPath[i];

			if (withRedLastPath == -1
				&& withBlueLastPath == -1) {
				shortestPathLength[i] = -1;
			} else if (withRedLastPath == -1) {
				shortestPathLength[i] = withBlueLastPath;
			} else if (withBlueLastPath == -1) {
				shortestPathLength[i] = withRedLastPath;
			} else {
				shortestPathLength[i] = Math.min(withRedLastPath, withBlueLastPath);
			}
		}

		return shortestPathLength;
	}

在 LeetCode 查看

本文由作者按照 CC BY 4.0 进行授权