Skip to content

Commit 8a9b034

Browse files
author
robot
committed
feat: $1129
1 parent 883742c commit 8a9b034

File tree

3 files changed

+150
-16
lines changed

3 files changed

+150
-16
lines changed

README.md

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,6 @@ leetcode 题解,记录自己的 leetcode 解题之路。
194194
- [0125. 验证回文串](./problems/125.valid-palindrome.md)
195195
- [0136. 只出现一次的数字](./problems/136.single-number.md)
196196

197-
<details>
198-
199-
<summary> :point_right::point_right::point_right:展开全部:point_left::point_left::point_left:</summary>
200-
201197
- [0155. 最小栈](./problems/155.min-stack.md) 👍
202198
- [0160. 相交链表](./problems/160.Intersection-of-Two-Linked-Lists.md) 91
203199
- [0167. 两数之和 II 输入有序数组](./problems/167.two-sum-ii-input-array-is-sorted.md)
@@ -228,8 +224,6 @@ leetcode 题解,记录自己的 leetcode 解题之路。
228224
- [1260. 二维网格迁移](./problems/1260.shift-2d-grid.md)
229225
- [1332. 删除回文子序列](./problems/1332.remove-palindromic-subsequences.md)
230226

231-
</details>
232-
233227
### 中等难度题目合集
234228

235229
中等题目是力扣比例最大的部分,因此这部分我的题解也是最多的。 大家不要太过追求难题,先把中等难度题目做熟了再说。
@@ -274,10 +268,6 @@ leetcode 题解,记录自己的 leetcode 解题之路。
274268
- [0061. 旋转链表](./problems/61.Rotate-List.md) 91
275269
- [0062. 不同路径](./problems/62.unique-paths.md)
276270
- [0073. 矩阵置零](./problems/73.set-matrix-zeroes.md)
277-
278-
<details>
279-
<summary> :point_right::point_right::point_right:展开全部:point_left::point_left::point_left:</summary>
280-
281271
- [0075. 颜色分类](./problems/75.sort-colors.md) 👍
282272
- [0078. 子集](./problems/78.subsets.md)
283273
- [0079. 单词搜索](./problems/79.word-search.md)
@@ -379,6 +369,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
379369
- [1031. 两个非重叠子数组的最大和](./problems/1031.maximum-sum-of-two-non-overlapping-subarrays.md)
380370
- [1043. 分隔数组以得到最大和](./problems/1043.partition-array-for-maximum-sum.md)
381371
- [1104. 二叉树寻路](./problems/1104.path-in-zigzag-labelled-binary-tree.md)
372+
- [1129. 颜色交替的最短路径](./problems/1129.shortest-path-with-alternating-colors.md)
382373
- [1131.绝对值表达式的最大值](./problems/1131.maximum-of-absolute-value-expression.md)
383374
- [1186. 删除一次得到子数组最大和](./problems/1186.maximum-subarray-sum-with-one-deletion.md)
384375
- [1218. 最长定差子序列](./problems/1218.longest-arithmetic-subsequence-of-given-difference.md)
@@ -399,7 +390,6 @@ leetcode 题解,记录自己的 leetcode 解题之路。
399390
- [1697. 检查边长度限制的路径是否存在](./problems/1697.checking-existence-of-edge-length-limited-paths.md) 🆕
400391
- [1737. 满足三条件之一需改变的最少字符数](./problems/1737.change-minimum-characters-to-satisfy-one-of-three-conditions.md) 🆕
401392
- [1834. 单线程 CPU](./problems/1834.single-threaded-cpu.md) 🆕
402-
</details>
403393

404394
### 困难难度题目合集
405395

@@ -462,9 +452,6 @@ leetcode 题解,记录自己的 leetcode 解题之路。
462452
- [0312. 戳气球](./problems/312.burst-balloons.md)
463453
- [330. 按要求补齐数组](./problems/330.patching-array.md)
464454

465-
<details>
466-
<summary> :point_right::point_right::point_right:展开全部:point_left::point_left::point_left:</summary>
467-
468455
- [0335. 路径交叉](./problems/335.self-crossing.md)
469456
- [0460. LFU 缓存](./problems/460.lfu-cache.md)
470457
- [0472. 连接词](./problems/472.concatenated-words.md)
@@ -497,8 +484,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
497484
- [1707. 与数组中元素的最大异或值](./problems/5640.maximum-xor-with-an-element-from-array.md)
498485
- [1723. 完成所有工作的最短时间](./problems/1723.find-minimum-time-to-finish-all-jobs.md) 🆕
499486
- [1835. 所有数对按位与结果的异或和](./problems/1835.find-xor-sum-of-all-pairs-bitwise-and.md) 🆕
500-
501-
</details>
487+
>
502488
503489
## :trident: &nbsp;anki 卡片
504490

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@
229229
- [1031. 两个非重叠子数组的最大和](./problems/1031.maximum-sum-of-two-non-overlapping-subarrays.md)
230230
- [1043. 分隔数组以得到最大和](./problems/1043.partition-array-for-maximum-sum.md) 👍
231231
- [1104. 二叉树寻路](./problems/1104.path-in-zigzag-labelled-binary-tree.md) 👍
232+
- [1129. 颜色交替的最短路径](./problems/1129.shortest-path-with-alternating-colors.md)
232233
- [1131.绝对值表达式的最大值](./problems/1131.maximum-of-absolute-value-expression.md) 👍
233234
- [1186. 删除一次得到子数组最大和](./problems/1186.maximum-subarray-sum-with-one-deletion.md) 👍
234235
- [1218. 最长定差子序列](./problems/1218.longest-arithmetic-subsequence-of-given-difference.md) 👍
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
## 题目地址(1129. 颜色交替的最短路径)
2+
3+
https://leetcode-cn.com/problems/shortest-path-with-alternating-colors/
4+
5+
## 题目描述
6+
7+
```
8+
在一个有向图中,节点分别标记为 0, 1, ..., n-1。这个图中的每条边不是红色就是蓝色,且存在自环或平行边。
9+
10+
red_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的红色有向边。类似地,blue_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的蓝色有向边。
11+
12+
返回长度为 n 的数组 answer,其中 answer[X] 是从节点 0 到节点 X 的红色边和蓝色边交替出现的最短路径的长度。如果不存在这样的路径,那么 answer[x] = -1。
13+
14+
 
15+
16+
示例 1:
17+
18+
输入:n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
19+
输出:[0,1,-1]
20+
21+
22+
示例 2:
23+
24+
输入:n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
25+
输出:[0,1,-1]
26+
27+
28+
示例 3:
29+
30+
输入:n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
31+
输出:[0,-1,-1]
32+
33+
34+
示例 4:
35+
36+
输入:n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
37+
输出:[0,1,2]
38+
39+
40+
示例 5:
41+
42+
输入:n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]]
43+
输出:[0,1,1]
44+
45+
46+
 
47+
48+
提示:
49+
50+
1 <= n <= 100
51+
red_edges.length <= 400
52+
blue_edges.length <= 400
53+
red_edges[i].length == blue_edges[i].length == 2
54+
0 <= red_edges[i][j], blue_edges[i][j] < n
55+
```
56+
57+
## 前置知识
58+
59+
- BFS
60+
61+
## 公司
62+
63+
- 暂无
64+
65+
## 思路
66+
67+
如果这道题不是求从 0 到 i 的红蓝相间的最短路径长度,而是**从 0 到 i 的最短红色最短路径长度**, 你会求解么?
68+
69+
实际上,这就 变成了一个简单的 BFS。
70+
71+
我们只需要根据 red_edges 建立邻接矩阵。接下来使用常规的 BFS 从 0 开始遍历,每遍历到一个节点就将其更新到答案中去即可。
72+
73+
那么问题扩展到红蓝相间有什么不同呢?不难发现,当本次边是红色的时候,下次我们需要从相邻的边中挑选一个蓝的边。如果本次是蓝色的边,则需要下次挑选一个红色的边。
74+
75+
这提示我们记录当前需要挑选的边的颜色是什么(红还是蓝)。
76+
77+
最直接的想法是建立两个队列。
78+
79+
- 一个是以红色边开始
80+
- 另一个是以蓝色边开始
81+
82+
如果是蓝色边开始,显然需要从 blue_edges 建立的临界矩阵中挑一个蓝色的边。挑选完毕之后,我们需要下次再挑选红色的边,以此类推。如果从红色边开始也是类似的,不再分析。
83+
84+
实际上,我们也可以使用一个队列。队列中存储的不是单一值,而是一个元祖,这样我们就可以将**当前的边颜色**信息存储到队列中。这样每次从队列中 pop 一个出来,就可直接根据 pop 出来的颜色来决定应该去红色边还是蓝色边了。
85+
86+
这里我使用 1 和 - 1 这样的一对相反数分别表示红色和蓝色,这样我就可以直接取相反数得到下一次 push 进队列的颜色是什么,而不用谢 if else 语句。
87+
88+
## 关键点
89+
90+
-
91+
92+
## 代码
93+
94+
- 语言支持:Python3
95+
96+
Python3 Code:
97+
98+
```python
99+
100+
101+
class Solution:
102+
def shortestAlternatingPaths(self, n: int, red_edges: List[List[int]], blue_edges: List[List[int]]) -> List[int]:
103+
ans = [2 * n] * n
104+
neibors_red = collections.defaultdict(list)
105+
neibors_blue = collections.defaultdict(list)
106+
# 1. 建立邻接矩阵
107+
for fr, to in red_edges:
108+
neibors_red[fr].append(to)
109+
for fr, to in blue_edges:
110+
neibors_blue[fr].append(to)‘
111+
# 将颜色也存入到队中
112+
q = collections.deque([(0, -1), (0, 1)])
113+
steps = 0
114+
115+
while q:
116+
for _ in range(len(q)):
117+
cur, color = q.popleft()
118+
ans[cur] = min(ans[cur], steps)
119+
# color == 1 该取红边了,否则取蓝边
120+
neibors = neibors_red if color == 1 else neibors_blue
121+
for nxt in neibors[cur]:
122+
q.append((nxt, -1 * color))
123+
# 此处的作用等同于 visited,即防止环的产产生。
124+
neibors[cur] = []
125+
steps += 1
126+
127+
return [-1 if a == 2 * n else a for a in ans]
128+
129+
130+
```
131+
132+
**复杂度分析**
133+
134+
令 n 为数组长度。
135+
136+
- 时间复杂度:$O(n)$
137+
- 空间复杂度:$O(n)$
138+
139+
> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。
140+
141+
力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~
142+
143+
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
144+
145+
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。
146+
147+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)

0 commit comments

Comments
 (0)