「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战」
题目
这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]。
请你判断自己是否能够跳到对应元素值为 0 的 任一 下标处。
注意,不管是什么情况下,你都无法跳到数组之外。
示例1
输入:arr = [4,2,3,0,3,1,2], start = 5
输出:true
解释:
到达值为 0 的下标 3 有以下可能方案:
下标 5 -> 下标 4 -> 下标 1 -> 下标 3
下标 5 -> 下标 6 -> 下标 4 -> 下标 1 -> 下标 3
示例2
输入:arr = [4,2,3,0,3,1,2], start = 0
输出:true
解释:
到达值为 0 的下标 3 有以下可能方案:
下标 0 -> 下标 4 -> 下标 1 -> 下标 3
示例3
输入: arr = [3,0,2,1,2], start = 2
输出: false
解释: 无法到达值为 0 的下标 1 处。
提示
1 <= arr.length <= 5 * 10^40 <= arr[i] < arr.length0 <= start < arr.length
题解
DFS
对于任意位置 , 可以跳到 或者 , 我们是不是可以从数组下标 处开始,向或者 深度搜索?可以吧,
伪代码:
dfs(start)
function dfs(idx){
// 向arr[idx] + idx方向搜索
dfs(idx + arr[idx])
// 向arr[idx] - idx方向搜索
dfs(idx - arr[idx])
}
深度递归要有中止条件啊,在这个跳跃游戏中终止条件是什么呢?
题目要求:跳到对应元素值为0的任一下标处,所以递归中止条件是:
dfs(start)
function dfs(idx){
if(arr[idx] === 0) return;
dfs(idx + arr[idx])
dfs(idx - arr[idx])
}
还是不行啊,如果不能跳转到元素值为0的下标呢?比如进入了一个循环,来回循环跳转这么处理呢?
这就需要一个额外数组空间 存储已经跳转过的路径了,假设已经跳转过的路径,直接返回终止递归
// 初始值额外空间为空
let list = []
dfs(start)
function dfs(idx){
// 如果额外空间在idx出有值,判定当前下标已经访问过,终止递归
if(list[idx]) return;
//记录访问过的下标
list[idx] = 1;
if(arr[idx] === 0) return
dfs(idx + arr[idx])
dfs(idx - arr[idx])
}
向或者 深度搜索,或者 可能会出现数组越界呀。所以需要再加判断,如果idx越界,终止递归
// 初始值额外空间为空
dfs(start)
function dfs(idx){
// 如果idx越界,终止递归
if( idx < 0 || idx >= len) return
dfs(idx + arr[idx])
dfs(idx - arr[idx])
}
综上所述思路编辑代码如下
完整代码
var canReach = function (arr, start) {
const len = arr.length;
const list = Array(len).fill(0);
return dfs(start);
function dfs(idx) {
if (arr[idx] === 0) return true;
if (list[idx]) return false;
list[idx] = 1;
if (idx < 0 || idx >= len) return false;
return dfs(idx + arr[idx]) || dfs(idx - arr[idx]);
}
};
BFS
理解了DFS就比较容易理解BFS了。
- 使用 存储可以访问的数组下标队列
- 从 取一位数组下标,计算 或者
- 如果或者 没有越界,没有访问过,将数据添加到
- 直到 为空,或者找到元素为0的下标
- 返回结果
完整代码
var canReach = function (arr, start) {
const len = arr.length;
const list = Array(len).fill(0);
const stack = [start];
while (stack.length) {
const p = stack.pop();
if (arr[p] === 0) return true;
const left = p + arr[p];
if (left >= 0 && left < len && list[left] === 0) {
stack.push(left);
list[left] = 1;
}
const right = p - arr[p];
if (right >= 0 && right < len && list[right] === 0) {
stack.push(right);
list[right] = 1;
}
}
return false;
};