【力扣-贪心】5、跳跃游戏I(55)II(45) 55 跳

「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

55. 跳跃游戏

题目描述

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1:

1
2
3
ini复制代码输入: nums = [2,3,1,1,4]
输出: true
解释: 可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

示例 2:

1
2
3
ini复制代码输入: nums = [3,2,1,0,4]
输出: false
解释: 无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。

解析

在计算是否能跳跃到最后一个位置,不需要考虑每次要跳 1步还是几步,只需要判断 调到的一格 是否能跳到最后一个数组元素位置,每次取最大的跳跃步数,判断是否有元素的跳跃范围达到最大的数组数目。

  • 贪心算法:
    • 局部最优:每次取最大的跳跃距离
    • 全局最优:最后判断局部最优中是否有能满足条件的,满足则就是全局最优的结果

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
c++复制代码class Solution
{
public:
bool canJump(vector<int> &nums)
{
int cover = 0;
if (nums.size() == 1)
{
return true;
}

for (int i = 0; i <= cover; i++)
{
// 记录每一步的最大跳跃范围
cover = max(i + nums[i], cover);
// 如果跳跃的范围能够满足数组的数目,则可以到达最后一个下标
if (cover >= nums.size() - 1)
{
return true;
}
}
}
};

45. 跳跃游戏 II

题目描述

给你一个非负整数数组 nums ,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

示例 1:

1
2
3
4
makefile复制代码输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
  从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

示例 2:

1
2
ini复制代码输入: nums = [2,3,0,1,4]
输出: 2

解析

与上一题思路相似,判断每一步能够到达的最远下标。如果当前能到达最远下标,则停止;如果不能到达最远下标,就继续走一步,判断下一步能否到达最远下标。

  • 当移动下标到达了当前覆盖的最远距离下标时:
    • 1、如果当前覆盖的最远距离下标时终点,直接返回,不需再走一步
    • 2、如果当前覆盖的最远距离下标不是终点,需要再走一步

代码

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
36
37
38
39
40
41
c++复制代码class Solution
{
public:
int jump(vector<int> &nums)
{
// 当前覆盖的最远下标
int curDistance = 0;
// 下一步覆盖的最远距离下标
int nextDistance = 0;
// 最大步数
int steps = 0;

for (int i = 0; i < nums.size(); i++)
{
// 更新下一步覆盖的最远下标
nextDistance = max(nextDistance, nums[i] + i);
// 遇到当前的最大覆盖下标
if (i == curDistance)
{
// 如果当前的最大覆盖下标还不是最后一个元素的下标
// 就需要再走一步
if (curDistance != nums.size() - 1)
{
steps++;
curDistance = nextDistance;
// 如果下一步的最大覆盖下标已经可以到达最后一个元素就停止
if (nextDistance >= nums.size() - 1)
{
break;
}
}
// 如果是终点就停止
else
{
break;
}
}
}
return steps;
}
};

改进

不考虑移动后是否到达终点

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
c++复制代码class Solution
{
public:
int jump(vector<int> &nums)
{
// 当前覆盖的最远下标
int curDistance = 0;
// 最大步数
int steps = 0;
// 下一步覆盖的最远下标
int nextDistance = 0;

// 这里下标 i < nums.size()-1
for (int i = 0; i < nums.size() - 1; i++)
{
// 更新下一步的最远覆盖下标
nextDistance = max(nextDistance, nums[i] + i);
// 遇到当前覆盖的最远下标时
if (i == curDistance)
{
// 更新当前覆盖的最远下标
curDistance = nextDistance;
steps++;
}
}
return steps;
}
};

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%