题目回顾:
问题核心:
给定一个长度为N的数组array,其中每个元素表示该位置的能量值。机器人从第一个位置(索引0)开始,可以消耗当前位置的能量值向前移动相应的步数。如果某个位置的能量值为0,则机器人无法继续前进。目标是判断机器人是否能够到达最后一个位置(索引N-1)。
其中需要注意的地方:
-
能量消耗与移动:每次移动时,机器人需要消耗当前位置的能量值来决定它可以向前走多少步。这意味着,如果当前位的能量值为0,那么机器人将无法继续前进。
-
目标:目标是到达数组的最后一个位置(索引为
n-1)。 -
条件:机器人可以不动,也可以向前走最多等于当前位置能量值的步数。但是,它不能向后移动或跳跃超过给定能量值所允许的最大步数。
解题思路
1.贪心算法:
贪心算法的核心思想是从当前可达的最远位置出发,逐步尝试扩展这个范围,直到确定是否能到达终点或无法再前进。
- 初始化:设定一个变量
maxReach表示当前能够达到的最远位置,初始时设为0。 - 遍历数组:
- 对于每一个位置
i,检查i是否超过了maxReach。如果超过,说明机器人无法到达位置i,直接返回"FALSE"。 - 更新
maxReach。对于每一个位置i,maxReach更新为max(maxReach, i + array[i])。这意味着机器人可以利用当前位置的能量值尽可能向前走。 - 如果在任何时候
maxReach大于或等于n-1,则意味着机器人可以到达终点,返回"TRUE"。
- 对于每一个位置
- 结束条件:如果遍历完所有位置后
maxReach仍小于n-1,则返回"FALSE"。
代码示例:
def solution(n, array):
maxReach = 0
for i in range(n):
if i > maxReach:
return "FALSE"
# 更新最大可达位置
maxReach = max(maxReach, i + array[i])
# 如果最大可达位置已经覆盖了终点
if maxReach >= n - 1:
return "TRUE"
return "FALSE"
# 测试用例
print(solution(5, [2, 3, 1, 1, 4]))
print(solution(5, [3, 2, 1, 0, 4]))
print(solution(6, [1, 2, 3, 4, 0, 0]))
这种算法的时间复杂度是O(n),空间复杂度是O(1)。
2.动态规划:
动态规划方法通过构建一个状态数组来记录从起点到每个位置是否可达。这种方法提供了另一种解决问题的角度,但可能不如贪心算法高效。
-
状态定义:定义一个布尔数组
dp,其中dp[i]表示能否到达位置i。 -
初始状态:设置
dp[0] = True,因为起点总是可达的。 -
状态转移:
- 对于每一个位置
i,如果dp[i]为True,则更新所有可以通过i处能量值到达的新位置的状态。 - 即对于每一个
j,如果1 <= j <= array[i]且i + j < n,则设置dp[i + j] = True。
- 对于每一个位置
-
最终状态:检查
dp[n-1]是否为True,以确定是否可以到达终点。
代码示例:
def solution(n, array):
dp = [False] * n
dp[0] = True # 起点总是可达的
for i in range(n):
if dp[i]: # 如果当前位置是可达的
# 更新所有可以从当前位置跳转到的位置
for step in range(1, array[i] + 1):
if i + step < n:
dp[i + step] = True
else: # 如果已经超出数组范围,直接返回 TRUE
return "TRUE"
return "TRUE" if dp[-1] else "FALSE"
# 测试用例
print(solution(5, [2, 3, 1, 1, 4]))
print(solution(5, [3, 2, 1, 0, 4]))
print(solution(6, [1, 2, 3, 4, 0, 0]))
总结
- 贪心算法:适用于此问题,因为它简单且高效,时间复杂度为O(n),空间复杂度为O(1)。
- 动态规划:虽然也可以解决此问题,但在时间和空间上都不如贪心算法高效,但它提供了一种不同的思考方式,有助于理解问题的本质。
选择哪种方法取决于具体需求和偏好。对于大多数实际应用,贪心算法将是首选。