LeetCode.跳跃游戏VII

跳跃游戏VII(dp)

1.题目描述

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

  • i + minJump <= j <= min(i + maxJump, s.length - 1) 且 s[j] == '0'.
     如果你可以到达 s 的下标 s.length - 1 处,请你返回 true ,否则返回 false 。
    原题链接:https://leetcode-cn.com/problems/jump-game-vii
2.简析

  这道题的数据范围是2 <= s.length <= 10^5,s[i] \in \{'0','1'\}; 因此这里考虑采用O(n)复杂度的算法,首先考虑dp;首先定义一个数组f[n]f[i]表示是否能移动到当前下标i。而能否移动到下标 i 取决于之前的状态,当s[i]=='1',f[i]=0; 否则其状态转移方程如下:
f[i] = \sum_{j = max(0, i-maxJump)}^{min(0, i-minJump)}{f[j]} > 0
但是针对每个下标点 i,都需要遍历前面 [i-maxJump, i-minJump]的元素,算法复杂度仍为 O(n^2)。由于这里是求这个范围内是否存在1,因此可以采用前缀和进行优化,在dp过程中同时记录前缀和,然后状态转移的时候可以利用前缀和在O(1)的时间复杂度内判断当坐标点是否可以由目标区间内某点转移而来,最终整个算法的复杂度为O(n)

3.代码示例
bool canReach(string s, int minJump, int maxJump) {
        int n = s.size();
        if(s[n-1] == '1') return false;
        int presum[n+1], f[n];
        memset(presum, 0, sizeof presum);
        memset(f, 0, sizeof f);
        f[0] = presum[1] = 1;
        for(int i=1; i<n; ++i){
            if(s[i] == '0' && i >= minJump){
               f[i] = presum[i+1-minJump] - presum[max(0, i-maxJump)] > 0? 1 : 0;
            }
            presum[i+1] = presum[i] + f[i];
        }
        return f[n-1]>0;
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 退役挺久了,现在写题竟是很慢了,不敢说自己打过ACM,LeetCode上的题似乎在面试的时候容易被问到,就写写,来...
    hdychi阅读 300评论 0 0
  • LeetCode 刷题随手记 - 第一部分 前 256 题(非会员),仅算法题,的吐槽 https://leetc...
    蕾娜漢默阅读 17,962评论 2 36
  • 为了给刷题的同学一些奖励,力扣团队引入了一个弹簧游戏机。游戏机由 N 个特殊弹簧排成一排,编号为 0 到 N-1。...
    _NewMoon阅读 648评论 0 2
  • 读完本文,你可以去力扣拿下如下题目: 55.跳跃游戏[https://leetcode-cn.com/proble...
    labuladong阅读 711评论 0 3
  • 给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度...
    Shimmer_阅读 217评论 0 1