题目描述
给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。
每一步,你可以从下标 i 跳到下标:
- i + 1 满足:i + 1 < arr.length
- i - 1 满足:i - 1 >= 0
- j 满足:arr[i] == arr[j] 且 i != j
请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。
注意:任何时候你都不能跳到数组外面。
示例 1:
输入:arr = [100,-23,-23,404,100,23,23,23,3,404]
输出:3
解释:那你需要跳跃 3 次,下标依次为 0 --> 4 --> 3 --> 9 。下标 9 为数组的最后一个元素的下标。
示例 2:
输入:arr = [7]
输出:0
解释:一开始就在最后一个元素处,所以你不需要跳跃。
示例 3:
输入:arr = [7,6,9,6,9,6,9,7]
输出:1
解释:你可以直接从下标 0 处跳到下标 7 处,也就是数组的最后一个元素处。
示例 4:
输入:arr = [6,1,9]
输出:2
示例 5:
输入:arr = [11,22,7,7,7,7,7,7,7,22,13]
输出:3
提示:
- 1 <= arr.length <= 5 * 10^4
- -10^8 <= arr[i] <= 10^8
题解思路
我们可以将数组抽象为一个无向图, 相邻元素之间用一根边连接,值相同的元素也用一根边连接。边的权重都为1即无
权图
求第一个元素到最后一个元素的最少操作次数 也就是求第一个元素到最后一个元素的最短路径
求无权图的最短路径可以用广度优先遍历来求解, 算法复杂度为o(V+E) 其中V为顶点个数为n 其中E为边的个数为
n**2 这样会导致超时,
我们只需要在第一次访问到子图某个节点的时候 将其未在队列的节点都放入队列之中,在第二次访问到这个节点的时候
就不需要去考虑子图中的其他节点了
题解代码
class Solution:
def minJumps(self, arr: List[int]) -> int:
samevalind=defaultdict(list)
for i,val in enumerate(arr):
samevalind[val].append(i)
visited=set()
q=deque()
q.append([0,0])
visited.add(0)
while q:
ind,step=q.popleft()
if ind==len(arr)-1:
return step
step+=1
v=arr[ind]
for i in samevalind[v]:
if i not in visited:
visited.add(i)
q.append([i,step])
del samevalind[v]
if ind+1<len(arr) and (ind+1) not in visited:
visited.add(ind+1)
q.append([ind+1,step])
if ind-1>=0 and (ind-1) not in visited:
visited.add(ind-1)
q.append([ind-1,step])