-
理解问题:
- 我们需要从数组的第一个元素开始跳跃,目标是到达数组的最后一个元素。
- 第一步的步长必须在1和数组长度的一半之间(不包含)。
- 从第二步开始,每次跳跃的步长由当前位置的元素值决定。
- 如果无法到达最后一个元素,返回
-1。
-
数据结构选择:
- 使用队列(Queue)来实现广度优先搜索(BFS),因为BFS可以保证找到最短路径。
- 使用一个集合来记录已经访问过的位置,避免重复访问。
-
算法步骤:
-
初始化一个队列,将起始位置和步数(初始为0)入队。
-
初始化一个集合,记录已经访问过的位置。
-
从队列中取出当前位置和步数:
- 如果当前位置是最后一个元素,返回步数。
- 否则,根据当前位置的元素值计算下一步的可能位置,并将其入队。
- 标记这些位置为已访问。
-
如果队列为空且没有找到目标位置,返回
-1。 -
- 初始步长范围:
-
min_step = 1 -
max_step = n // 2
-
-
BFS队列:
- 使用
deque来实现队列,初始化时将起始位置0和步数0入队。
- 使用
-
访问控制:
- 使用
visited集合来记录已经访问过的位置,避免重复访问。
- 使用
-
BFS过程:
- 如果是第一步,遍历所有可能的步长。
- 从第二步开始,步长由当前位置的元素值决定。
- 如果到达最后一个元素,返回当前步数。
总结
通过广度优先搜索(BFS)算法,我们可以有效地找到从数组第一个元素到数组最后一个元素的最少步数。BFS的特性保证了我们找到的路径是最短的,因为它会优先探索距离起点最近的节点。在这个问题中,我们通过队列来实现BFS,并使用集合来记录已经访问过的位置,避免重复访问。
初始步长的限制和后续步长的动态变化增加了问题的复杂性,但通过合理的算法设计和数据结构选择,我们可以有效地解决这个问题。通过逐步实现和测试代码,我们可以验证算法的正确性和效率。
from collections import deque
def solution(arr: list) -> int:
n = len(arr)
if n == 1:
return 0
# 初始步长范围
min_step = 1
max_step = n // 2
# 使用队列进行BFS
queue = deque([(0, 0)]) # (当前位置, 步数)
visited = set()
visited.add(0)
while queue:
pos, steps = queue.popleft()
# 如果是第一步,步长在min_step和max_step之间
if steps == 0:
for step in range(min_step, max_step):
next_pos = pos + step
if next_pos < n and next_pos not in visited:
queue.append((next_pos, steps + 1))
visited.add(next_pos)
else:
# 从第二步开始,步长由当前位置的元素值决定
step = arr[pos]
next_pos = pos + step
if next_pos >= n:
continue
if next_pos == n - 1:
return steps + 1
if next_pos not in visited:
queue.append((next_pos, steps + 1))
visited.add(next_pos)
return -1
if __name__ == '__main__':
print(solution(arr=[7, 5, 9, 4, 2, 6, 8, 3, 5, 4, 3, 9]) == 2)
print(solution(arr=[2, 3, 1, 1, 4]) == 2)
print(solution(arr=[1, 2, 1, 1, 0]) == 3)