55. 跳跃游戏

如果当前数字为3,代表在这一格可以跳1或2或3格

维护一个全局最远可到达的下标 maxReach

遍历 nums 数组,如果 maxReach 小于当前下标 i ,说明现在这里就不可以到达,更别说终点了,return false

接下来就是现在这个下标可以到达的情况

现在这个下标的最远可到达为 当前位置加最远可跳 i+nums[i] ,将它与全局的最远可跳 maxReach 比较并更新

直到退出循环都没有提前返回 false,说明全局最远可到达所有下标包括终点 —— return true 

class Solution {
    public boolean canJump(int[] nums) {
        // 全局的最远可到达下标
        int maxReach = 0;
        for (int i=0;i<nums.length;i++) {
            // 如果在更新全局的最远可达到之前,它已经小于当前下标了,说明当前下标就到不了,终点更到不了
            if (maxReach < i) {
                return false;
            }
            // 当前下标最远可到达,为当前下标加上当前可以跳的最远的(如果是3,那么可以跳1或2或3步)
            int curIndexMaxReach = i + nums[i];
            maxReach = Math.max(maxReach, curIndexMaxReach);
        }
        return true;
    }
}

 

45. 跳跃游戏 II

 

参照官方题解 方法二

https://leetcode.cn/problems/jump-game-ii/solution/tiao-yue-you-xi-ii-by-leetcode-solution/

例如,对于数组 [2,3,1,2,4,2,3],初始位置是下标 0,从下标 0 出发,最远可到达下标 2。下标 0 可到达的位置中,下标 1 的值是 3,从下标 1 出发可以达到更远的位置,因此第一步到达下标 1。

从下标 1 出发,最远可到达下标 4。下标 1 可到达的位置中,下标 4 的值是 4 ,从下标 4 出发可以达到更远的位置,因此第二步到达下标 4。

class Solution {
    public int jump(int[] nums) {
        
        int jumpCount = 0;
        int nowIndex = 0;
        while(nowIndex < nums.length-1) {
            
            // 跳到当前位置后,能跳到的最远位置
            int canJumpFarthestIndex = nowIndex + nums[nowIndex];
            // 最远就已经到终点了,这是最后一跳,不用继续往下走了
            if (canJumpFarthestIndex >= nums.length - 1) {
                jumpCount++;
                break;
            }

            // 为了后面的选择,不一定就跳到最远, 1~canJunmFarthest 都可以跳
           // 从 1~canJunmFarthest 里选出下次可以跳的最远的
            int selectedCanJumpIndex = canJumpFarthestIndex;
            int canJumpIndexNextJumpFarthest = canJumpFarthestIndex + nums[canJumpFarthestIndex];
            // 从跳 1~canJunmFarthest, 评估跳到这个位置后,下次跳哪个可以跳得更远, 选出最远的
            for (int canJumpIndex = nowIndex+1;canJumpIndex<=canJumpFarthestIndex;canJumpIndex++) {
                int canJumpIndexNextJump = canJumpIndex + nums[canJumpIndex];
                if (canJumpIndexNextJump >  canJumpIndexNextJumpFarthest) {
                    canJumpIndexNextJumpFarthest = canJumpIndexNextJump;
                    selectedCanJumpIndex = canJumpIndex;
                }
            }
            nowIndex = selectedCanJumpIndex;
            jumpCount++;
        } 

        return jumpCount;

    }
}

 

763. 划分字母区间 (贪心,用结束下标更新当前片段结束下标)

先遍历字符串,得到 字符-该字符最后一次出现的位置 的map

用一个 curStart 和 curEnd 来记录当前片段的起始下标和结束下标,初始值都为0

然后再次遍历字符串,如果 新字符的endIndex > curEnd,超出了当前片段,则扩充当前片段结束边界:curEnd = 字符endIndex

如果 i==curEnd ,经过前面的扩充,与一些字符的不扩充,终于走到了片段的结束

则将当前片段的长度 curEnd-curStart+1 添加到结果数组中,同时下一个片段要开始了:curStart=i+1 curEnd=i+1

class Solution {
    public List<Integer> partitionLabels(String s) {
        // 得到 字符-该字符最后一次出现位置 的map
        Map<Character, Integer> char2EndMap = new HashMap();
        for (int i=0;i<s.length();i++) {
            char c = s.charAt(i);
            char2EndMap.put(c, i);
        }

        List<Integer> res = new ArrayList();
        // 当前片段起始位置
        int curStart = 0;
        // 当前片段结束位置
        int curEnd = 0;
        for (int i=0;i<s.length();i++) {
            char c = s.charAt(i);
            Integer cEndIndex = char2EndMap.get(c);
            // 这个片段内出现的新字符的endIndex大于当前片段的end,则更新
            if (cEndIndex>curEnd) {
                curEnd = cEndIndex;
            }
            // 当前片段走到了最后一个字符
            if (i == curEnd) {
                // 当前片段已经结束,将当前片段的长度添加到结果中
                res.add(curEnd - curStart + 1);
                // 现在下个片段开始了
                curStart = i+1;
                curEnd = i+1;
            }
        }
        return res;
    }
}