LeetCode55. Jump Game

一、问题描述

Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your [maximum][6] jump length at that position.
Determine if you are able to reach the last index.

For example:
A = [2,3,1,1,4], return true.
A = [3,2,1,0,4], return false.

题意解释:给定一个数组,数组的每一位的值表示从该位可以跳到其它位的最大位数,现由其数组的第一位数出发,按照以上规则进行随意跳转,如果最终能够到达数组的最一位,则返回true,否则返回false。

二、解题思路

若正面考虑问题,我们会发现有一个麻烦的问题:从某一位跳到另一位,target并不是唯一的,有多少种跳法取决于当前位的值。由此我们会发现,若正面解答问题,要遍历数组的每一位及从当前位跳转到下一位的所有跳法,直到找到一条符合条件(也即能到达最后一位)的路径,这种深度优先算法无疑是麻烦冗杂而且开销较大的。

由于我没有采用这种解法,所以在这里引用一下用这种思路解题的递归解法:

enum Index {
    GOOD, BAD, UNKNOWN
}

public class Solution {
    Index[] memo;

    public boolean canJumpFromPosition(int position, int[] nums) {
        if (memo[position] != Index.UNKNOWN) {
            return memo[position] == Index.GOOD ? true : false;
        }

        int furthestJump = Math.min(position + nums[position], nums.length - 1);
        for (int nextPosition = position + 1; nextPosition <= furthestJump; nextPosition++) {
            if (canJumpFromPosition(nextPosition, nums)) {
                memo[position] = Index.GOOD;
                return true;
            }
        }

        memo[position] = Index.BAD;
        return false;
    }

    public boolean canJump(int[] nums) {
        memo = new Index[nums.length];
        for (int i = 0; i < memo.length; i++) {
            memo[i] = Index.UNKNOWN;
        }
        memo[memo.length - 1] = Index.GOOD;
        return canJumpFromPosition(0, nums);
    }
}

我们不如换个思路解决问题。

既然最终的目标是到达数组的最后一位,那我们不如从最后一位开始,设该位为target,向前遍历,寻找能够跳转到target的位,并将target更新为这个位,再重复以上过程,直到target变成数组的第一位,即target==0,说明从第一位可以经过跳转过程到达最后一位。

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

代码较为简单,但有一个值得注意的细节,有的人可能会想,在我们倒序遍历数组的时候,每当找到能够跳转到target的位(假设把这个位叫做候选1号位),就将候选1号位的位数赋给target,那么如果存在比候选1号位更靠前的候选2号位,它同样能到达当前的target,可是我们忽视了它,那会不会出现把target赋予了候选1号位后,在target==0前就走进了死胡同,但若之前把target赋给候选2号位,却能达到target==0,因而导致我们错过了正确解呢?答案是不会的。
因为在候选1号位和候选2号位都可以跳转到target的情况下,由于1号位比2号位靠前,如果走1号位的路径使得问题有解的话,走2号位的路径也必然有解,只需在中间插入一次1号位到2号位,再从2号位到数组target的跳转。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值