《算法设计与分析》第七周作业
标签(空格分隔): 课堂作业
姓名:李**
学号:16340114
题目:Jump Game II(https://leetcode.com/problems/jump-game-ii/description/)
题目概要
初始位置为0。给定一个数列,数列的元素代表当前可以跳跃的最大距离。如果确定可以跳到最后一个元素,问跳到最后的位置最少需要几步。
思路
很显然这是一个贪心算法问题,解题的关键就在于怎么设计贪心策略了。我们每次进行跳跃之后都希望能跳到一个理想的位置,这个位置要距离终点足够近,并且这个位置能跳跃的最大距离也相对比较大。这样的话我们跳到一个理想位置之后,距离终点更近了,并且下一次跳跃的位置也有了更多的选择。只要我们从起点出发,每次都跳到这样的理想位置上,所用的步数就是最少的了。证明过程(略)
具体实现
我们这样定义一个理想值:理想值 = 当前位置下标 + 当前位置所能跳跃的最大距离
也就是说理想值是跳到那个位置之后最远能到达的地方的下标。
先把起点设成当前位置,算出理想值。遍历理想点所能到达的地方,计算他们的理想值。如果最大的理想值和当前位置的值一样,那就从当前位置直接跳到其所能到达的最远位置。如果有除当前位置之外有更大的理想值,那就跳到理想值最大的位置。重复这个操作,直到走到终点。
心得
贪心问题想到了贪心策略就很简单了,编程也不难。在想出这个方法之前我也想过每次走到最远距离的贪心策略,但这个策略的问题就在于跳到最远的位置可能会错过路上更好的位置,比如[3,120,1,…,1],如果一开始就从起点跳3格,就会错过第二格能跳120格的好位置。
所以我就想着更贪一点,先尝试跳得最远,跳完之后还能跳得最远,于是我的上述的策略就慢慢成型了。认真思考过这个没有发现这个策略的问题,列举了几种情况也还适用,抱着试试的心态交了一波,不出我意料,提交通过了。
感觉贪心算法就是目前要贪,贪完之后下一步继续贪,顺着这个思路想就对了。找不出反例的话,十有八九是对的~~,证明什么的就管他呢。~~
源码:
class Solution {
public:
int jump(vector<int>& nums)
{
if (nums.size() == 1)
return 0;
int steps = 1;
int currentPosition = 0;
while (currentPosition <= nums.size())
{
if (currentPosition + nums[currentPosition] >= nums.size() - 1)
return steps;
int nextIdealPosition = currentPosition;
int IdealValue = currentPosition + nums[currentPosition];
for (int i = currentPosition + 1; i <= currentPosition + nums[currentPosition]; ++i)
{
if ( i + nums[i] > IdealValue )
{
IdealValue = i + nums[i];
nextIdealPosition = i;
}
}
if (currentPosition == nextIdealPosition)
{
currentPosition = currentPosition + nums[currentPosition];
steps++;
}
else
{
currentPosition = nextIdealPosition;
steps++;
}
}
return 0;
}
};