zoukankan      html  css  js  c++  java
  • LeetCode——55. 跳跃游戏

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

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

    判断你是否能够到达最后一个位置。

    示例 1:

    输入: [2,3,1,1,4]
    输出: true
    解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。
    

    示例 2:

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

    动态规划

    这里可以用动态规划 Dynamic Programming 来解,维护一个一维数组 dp,其中 dp[i] 表示达到i位置时剩余的跳力,若到达某个位置时跳力为负了,说明无法到达该位置。

    接下来难点就是推导状态转移方程,到达当前位置的剩余跳力,其实是跟上一个位置的剩余跳力(dp 值)和上一个位置新的跳力(nums 数组中的值)有关,这里新的跳力就是原数组中每个位置的数字,因为其代表了以当前位置为起点能到达的最远位置。

    所以当前位置的剩余跳力(dp 值)和当前位置新的跳力中的较大那个数决定了当前能到的最远距离,而下一个位置的剩余跳力(dp 值)就等于当前的这个较大值减去1,因为需要花一个跳力到达下一个位置,所以就有状态转移方程了:dp[i] = max(dp[i - 1], nums[i - 1]) - 1,如果当某一个时刻 dp 数组的值为负了,说明无法抵达当前位置,则直接返回 false,最后循环结束后直接返回 true 即可,参见代码如下:

    c++

    class Solution {
    public:
        bool canJump(vector<int>& nums) {
            vector<int> dp(nums.size(), 0);
            for (int i = 1; i < nums.size(); ++i) {
                dp[i] = max(dp[i - 1], nums[i - 1]) - 1;
                if (dp[i] < 0) return false;
            }
            return true;
        }
    };
    

    java

    class Solution {
        public boolean canJump(int[] nums) {
            int[] dp = new int[nums.length];
            for(int i = 1; i < nums.length; ++i){
                dp[i] = Math.max(dp[i-1], nums[i-1]) - 1;
                if (dp[i] < 0) return false;
            }
            return true;
        }
    }
    

    贪婪算法

    这里并不是很关心每一个位置上的剩余步数,而只希望知道能否到达末尾,也就是说我们只对最远能到达的位置感兴趣,所以维护一个变量 reach,表示最远能到达的位置,初始化为0。

    遍历数组中每一个数字,如果当前坐标大于 reach 或者 reach 已经抵达最后一个位置则跳出循环,否则就更新 reach 的值为其和 i + nums[i] 中的较大值,其中 i + nums[i] 表示当前位置能到达的最大位置,参见代码如下:

    c++

    class Solution {
    public:
        bool canJump(vector<int>& nums) {
            int n = nums.size(), reach = 0;
            for (int i = 0; i < n; ++i) {
                if (i > reach || reach >= n - 1) break;
                reach = max(reach, i + nums[i]);
            }
            return reach >= n - 1;
        }
    };
    

    java

    public class Solution {
        public boolean canJump(int[] nums) {
            int lastPos = nums.length - 1;
            for (int i = nums.length - 1; i >= 0; i--) {
                if (i + nums[i] >= lastPos) {
                    lastPos = i;
                }
            }
            return lastPos == 0;
        }
    }
    

    python

    class Solution:
        def canJump(self, nums) :
            max_i = 0                          #初始化当前能到达最远的位置
            for i, jump in enumerate(nums):    #i为当前位置,jump是当前位置的跳数
                if max_i>=i and i+jump>max_i:  #如果当前位置能到达,并且当前位置+跳数>最远位置  
                    max_i = i+jump             #更新最远能到达位置
            return max_i>=i
    
  • 相关阅读:
    Python——极限编程
    RPC是什么?科普一下
    缓存在高并发场景下的常见问题
    如何提高缓存命中率
    数据库性能优化的误区
    缓存在大型网站架构中的应用
    APP多版本共存,服务端如何兼容?
    水平分库分表的关键问题及解决思路
    分库分表的几种常见玩法及如何解决跨库查询等问题
    分布式系统事务一致性解决方案
  • 原文地址:https://www.cnblogs.com/wwj99/p/12394843.html
Copyright © 2011-2022 走看看