leetcode 1871. 跳跃游戏 VII 中等

给你一个下标从 0 开始的二进制字符串 s 和两个整数 minJumpmaxJump 。一开始,你在下标 0 处,且该位置的值一定为 '0' 。当同时满足如下条件时,你可以从下标 i 移动到下标 j 处:

  • i + minJump <= j <= min(i + maxJump, s.length - 1)
  • s[j] == '0'.

如果你可以到达 s 的下标s.length - 1 处,请你返回 true ,否则返回 false

示例 1:

复制代码
输入:s = "011010", minJump = 2, maxJump = 3
输出:true
解释:
第一步,从下标 0 移动到下标 3 。
第二步,从下标 3 移动到下标 5 。

示例 2:

复制代码
输入:s = "01101110", minJump = 2, maxJump = 3
输出:false

提示:

  • 2 <= s.length <= 10^5
  • s[i] 要么是 '0' ,要么是 '1'
  • s[0] == '0'
  • 1 <= minJump <= maxJump < s.length

分析: 如果最后一个位置本身是 '1',那么一定无法到达,可以直接返回 false

先把字符串中所有字符为 '0' 的位置存入数组 pos 中,判断可以跳到哪些位置时,只需要在这些 '0' 位置中寻找,不需要反复扫描整个字符串。然后使用队列进行 BFS,队列中保存的是当前已经可以到达的位置。初始时,下标 0 一定是起点,所以先将 0 入队。对于队首位置 index,它下一步可以到达的范围是 [index + minJump, index + maxJump] 这个区间内,并且落点必须是 '0'

使用变量 temp 作为指针,指向 pos 数组中当前还没有处理过的位置。又因为 pos[0] 就是起点 0,因此 temp 初值为 1。当 BFS 扩展某个位置时,就从 pos[temp] 开始向后扫描。如果 pos[temp] < left,说明这个 '0' 位置太靠前,当前点跳不到它。由于 BFS 中后续取出的下标只会越来越大,之后的 left 也只会更靠后,所以这个位置以后也不可能再被跳到,可以直接跳过。

如果 pos[temp] > right,说明这个位置已经超过了当前能跳到的范围,后面的 pos 更大,也一定超过范围,所以停止本轮扫描。

如果 left <= pos[temp] <= right,说明这个位置可以从当前下标跳到,因此将它加入队列,后续继续从这个位置向外扩展。

这个 temp 是整个 BFS 共用的,而不是每次从头开始扫描。这样可以保证每个 '0' 位置最多只会被扫描一次,从而避免超时。

最后,只需要判断最后一个位置是否被访问过,如果 flag[len - 1] 为真,说明最后一个位置可以到达;否则说明无法到达。

cpp 复制代码
class Solution {
public:
    bool canReach(string s, int minJump, int maxJump) {
        if(s[s.length()-1]=='1')return false;
        vector<int>pos;
        int len=s.length(),n,temp=1;
        for(int i=0;i<len;++i)
            if(s[i]=='0')pos.push_back(i);
        queue<int>que;que.push(0);n=pos.size();
        map<int,int>flag;flag[0]=1;
        while(!que.empty())
        {
            int index=que.front();que.pop();flag[index]=1;
            int left=index+minJump,right=min(len-1,index+maxJump);

            if(left>right)continue;
            while(temp<n)
            {
                if(pos[temp]<left)temp++;
                else if(pos[temp]>right)break;
                else que.push(pos[temp]),flag[pos[temp]]=1,temp++;
            }
        }
        if(flag[len-1])return true;
        return false;
    }
};
相关推荐
想吃火锅10052 天前
【leetcode】121.买卖股票的最佳时机js/c++
算法·leetcode·职场和发展
凌波粒2 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
退休倒计时3 天前
【每日一题】LeetCode 146. LRU 缓存 TypeScript
算法·leetcode·缓存·typescript
小欣加油3 天前
leetcode3612 用特殊操作处理字符串I
数据结构·c++·算法·leetcode·职场和发展
凌波粒3 天前
LeetCode--90.子集II(回溯算法)
数据结构·算法·leetcode
凌波粒3 天前
LeetCode--46.全排列(回溯算法)
数据结构·算法·leetcode
吃着火锅x唱着歌3 天前
LeetCode 2530.执行K次操作后的最大分数
数据结构·算法·leetcode
sheeta19983 天前
LeetCode 每日一题笔记 日期:2026.06.16 题目:3612. 字符串特殊符号处理
笔记·算法·leetcode
CoderYanger3 天前
A.每日一题:2095. 删除链表的中间节点
java·数据结构·程序人生·leetcode·链表·面试·职场和发展
青山木3 天前
Hot 100 --- 矩阵置零
线性代数·算法·leetcode·矩阵·哈希算法