一、跳跃游戏
1、题目

2、分析
跟跳跃游戏Ⅱ一样。
3、代码
java
class Solution {
public boolean canJump(int[] nums) {
int left=0, right=0, maxIndex=0;
while (left <= right) {
if (right >= nums.length-1) return true;
for (int i = left; i <= right; i++) {
maxIndex = Math.max(maxIndex, nums[i] + i);
}
left = right+1;
right = maxIndex;
}
return false;
}
}
二、跳跃游戏Ⅱ
1、题目

2、分析
类似层序遍历,left 标记当前第 x 跳的左边界,right 标记当前第 x 跳的右边界,遍历 left 到 right 区间的值,计算 num[i]+i = 下一跳到达的位置,最大位置标记为 maxIndex,即下一跳的右边界。更新 left=right+1,right=maxIndex。

特殊情况,可能怎么跳都达到不了 n-1 的位置。即会出现 right < left 的情况,这个时候就要退出层序遍历,返回不可到达。

时间复杂度:O(n),只遍历了一遍数组。
3、代码
java
class Solution {
public int jump(int[] nums) {
int left=0, right=0, maxIndex=0, ret=0;
while (left <= right) {
if (right >= nums.length-1) return ret;
for (int i = left; i <= right; i++) {
maxIndex = Math.max(maxIndex, nums[i] + i);
}
left = right+1;
right = maxIndex;
ret++;
}
return -1;
}
}
三、划分字母区间
1、题目

2、分析
遍历数组,找到每种字母的右边界,用 hash 表存储,每种字母的最后一个字母的位置会覆盖前面的位置,从而获得每种字母的右边界。
再遍历数组,获取已经遍历过的字母中,右边界最大位置,如果最大位置就是当前遍历字母的右边界,则此字母是分割点。

时间复杂度:O(n)。遍历一遍数组,获取字母的右边界;又遍历了一遍数组,找到划分点。
3、代码
java
class Solution {
public List<Integer> partitionLabels(String s) {
char[] chars = s.toCharArray();
int n = chars.length;
int[] right_map = new int[26];
List<Integer> ret = new ArrayList<>();
int max_right = 0;
int index = -1; // 上一个划分点
// 初始化每种字母的右边界 map
for (int i = 0; i < n; i++) right_map[chars[i]-'a'] = i;
// 找划分点
for (int i = 0; i < n; i++) {
// 已遍历字母中,右边界的最大值
max_right = Math.max(max_right, right_map[chars[i]-'a']);
// 最大右边界刚好是该字母位置
if (max_right == i) {
ret.add(max_right - index);
index = max_right;
}
}
return ret;
}
}