[LeetCode 55 题 – 跳跃游戏] | 刷题打卡

掘金团队号上线,助你 Offer 临门! 点击 查看详情

前言

今天刷到的题主要是采用 贪心算法 实现。所谓贪心算法,就是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。比如在旅行推销员问题中,如果旅行员每次都选择最近的城市,那这就是一种贪心算法。

题目描述

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

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

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

 
示例 1:

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

示例 2:

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

提示

  • 1 <= nums.length <= 3 * 104
  • 0 <= nums[i] <= 105

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/im…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

这题最典型的做法应该就是采用 贪心 策略,对于着腿,我们首先可以得出一个结论:假设当前跳跃到 i 坐标。那么在 i 之前的所有坐标肯定都是可以到达的。所以我们只需要维护对于数组的每个元素,可以跳到的最远距离即可。那么对于第 i-1 个元素,他可以到达的最远距离为 i-1+num[i-1] 。假设此时我们维护的最大跳远距离为 k 。那么,那么在这个点能够跳到的最远距离就是 max(i-1+num[i-1],k) (因为对于 i-1 可能在他之前就有比他能够到达更远的距离 k)。我们再把这个最远距离维护到变量 k 中,根据刚刚得到的结论,只需要比较 k 和 i 的大小即可。

其他解法

我又看了一下 LeetCode 上面其他人的解法,有一些用到了回溯。大致的思路就是从终点(末位置)开始试探回溯。不只是终点,对于任意的一个点i,我们可以遍历[0,i-1]中的点j,如果有nums[j] >= i-j,那么就能够从点i到达点j,随之进一步考察j能否被[0,j-1]中的点到达。如果中途出现不可到达点,则回溯到上一层(离终点较近)的点。

class Solution {
public:
    //本质上是DFS:试探回溯
    bool trace_back(vector<int> & nums, int target)
    {   //判断能否从src到达target
        if (target==0)
            return true;//递归基

        for (int src = target-1; src >= 0; src--)
        {
            if (nums[src] >= target - src)
                return trace_back(nums, src);//继续沿着这个src往前找
        }

        return false;
    }

    bool canJump(vector<int>& nums) {
        int target = nums.size()-1;
        
        return trace_back(nums, target);
    }
};
复制代码

DFS解法转自作者:zongy17
链接:leetcode-cn.com/problems/ju…

最终代码

class Solution {
    public boolean canJump(int[] nums) {
        int k = 0;
        for (int i = 0; i < nums.length; i++) {
            if (i > k) return false;
            k = Math.max(k, i + nums[i]);
        }
        return true;
    }
}
复制代码

结语

虽然本题的 DFS 的解题效果在效率上并不理想,但是仍然是一种值得学习的思路。本文正在参与「掘金 2021 4 月刷题打卡」, 点击查看 活动详情。喜欢的话点个赞吧。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享