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;
    }
};
相关推荐
Rabitebla15 小时前
C++ 继承详解(下):默认成员函数、虚继承底层与设计取舍
c语言·开发语言·数据结构·c++·算法·leetcode
圣保罗的大教堂1 天前
leetcode 2540. 最小公共值 简单
leetcode
洛水水1 天前
【力扣100题】53.最长回文子串
算法·leetcode·职场和发展
过期动态1 天前
【LeetCode 热题 100】盛最多水的容器
java·数据结构·spring boot·算法·leetcode·spring cloud·职场和发展
凌波粒1 天前
LeetCode--700.二叉搜索树中的搜索(二叉树)
算法·leetcode·职场和发展
洛水水1 天前
【力扣100题】58.轮转数组
算法·leetcode
风筝在晴天搁浅1 天前
阿里 LeetCode 876.链表的中间节点
算法·leetcode·链表
玖釉-1 天前
二叉树展开为链表:从先序遍历到原地指针重排
c++·windows·算法·leetcode·链表
洛水水1 天前
【力扣100题】52.最小路径和
算法·leetcode