1345. 跳跃游戏 IV(Rating 1810)
1345. 跳跃游戏 IV(Rating 1810)
以下内容偏向于记录个人练习过程及思考,非常规题解内容
题目
思路
一眼bfs。可以连接的边是相同的数以及左右两边的数,建图后bfs即可找到最短路径。
但是潇洒写完一波后TLE了,代码如下
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
from collections import defaultdict
from collections import deque
class Solution:
def minJumps(self, arr: List[int]) -> int:
num_dict = defaultdict(list)
for idx, num in enumerate(arr):
num_dict[num].append(idx)
q = deque()
q.append(0)
vis = set()
vis.add(0)
ret = 0
while q:
sz = len(q)
while sz:
sz -= 1
idx = q.popleft()
num = arr[idx]
if idx == len(arr) - 1:
return ret
if idx - 1 >= 0 and idx - 1 not in vis:
q.append(idx - 1)
vis.add(idx - 1)
if idx + 1 < len(arr) and idx + 1 not in vis:
q.append(idx + 1)
vis.add(idx + 1)
for i in num_dict[num]:
if i not in vis:
q.append(i)
vis.add(i)
ret += 1
return -1
TLE的case类似于[7,7,7,7,7,7,…,7,7,11]
仔细分析下原因不难得出,虽然bfs复杂度是O(n)的,但每次遍历一个index时,都要重复遍历一遍相同的数判断是否需要加入队列,即罪魁祸首是下面这段代码在例如上面的特殊case下是O(n)的,所以整体的复杂度就变成了O(n^2)
1
2
3
4
for i in num_dict[num]:
if i not in vis:
q.append(i)
vis.add(i)
优化点也不难想到,循环遍历完一个数后,理论上其对应的所有index都已经加入到队列中了,因此可以在dict中删除该数字,避免在后面的遍历中重复判断。
代码如下
代码
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
from collections import defaultdict
from collections import deque
class Solution:
def minJumps(self, arr: List[int]) -> int:
num_dict = defaultdict(list)
for i, num in enumerate(arr): # 使用dict维护相同数字对应的下标,方便建图
num_dict[num].append(i)
q = deque() # 初始化队列
q.append(0)
vis = set() # 初始化访问过的index set
vis.add(0)
ret = 0
while q: # bfs 模板
sz = len(q)
while sz:
sz -= 1
idx = q.popleft()
if idx == len(arr) - 1: # 找到终点
return ret
if idx - 1 >= 0 and idx - 1 not in vis: # 添加左右两个index
q.append(idx - 1)
vis.add(idx - 1)
if idx + 1 < len(arr) and idx + 1 not in vis: # 添加左右两个index
q.append(idx + 1)
vis.add(idx + 1)
num = arr[idx]
for i in num_dict[num]: # 添加相同数字对应的index
if i not in vis:
q.append(i)
vis.add(i)
num_dict.pop(num) # 因为所有num对应的index已全部加入队列,所以在dict中删除该数字,后续避免重复判断
ret += 1
return -1
本文由作者按照 CC BY 4.0 进行授权