代码实现:
方法一:回溯 + 历史答案剪枝优化——超时
int *dis; void dfs(int k, int startindex, int *nums, int numsSize) { if (dis[startindex] <= k) { return; } dis[startindex] = k; for (int i = 0; i <= nums[startindex]; i++) { if (startindex + i > numsSize - 1) { continue; } dfs(k + 1, startindex + i, nums, numsSize); } } int jump(int *nums, int numsSize) { if (numsSize == 1) { return 0; } dis = malloc(sizeof(int) * numsSize); for (int i = 0; i < numsSize; i++) { dis[i] = numsSize + 1; } dfs(0, 0, nums, numsSize); return dis[numsSize - 1]; }
方法二:贪心
#define max(a, b) ((a) > (b) ? (a) : (b)) int jump(int *nums, int numsSize) { if (numsSize == 1) { return 0; } int cur = 0; // 当前覆盖最远距离下标 int ans = 0; // 记录走的最大步数 int next = 0; // 下一步覆盖最远距离下标 for (int i = 0; i < numsSize; i++) { next = max(nums[i] + i, next); // 更新下一步覆盖最远距离下标 if (i == cur) { // 遇到当前覆盖最远距离下标 if (cur != numsSize - 1) { // 如果当前覆盖最远距离下标不是终点 ans++; // 需要走下一步 cur = next; // 更新当前覆盖最远距离下标(相当于加油了) if (next >= numsSize - 1) { // 下一步的覆盖范围已经可以达到终点,结束循环 break; } } else { // 当前覆盖最远距离下标是集合终点,不用做ans++操作了,直接结束 break; } } } return ans; }