【1654. 到家的最少跳跃次数】

来源:力扣(LeetCode)

描述:

有一只跳蚤的家在数轴上的位置 x 处。请你帮助它从位置 0 出发,到达它的家。

跳蚤跳跃的规则如下:

  • 它可以 往前 跳恰好 a 个位置(即往右跳)。
  • 它可以 往后 跳恰好 b 个位置(即往左跳)。
  • 它不能 连续 往后跳 2 次。
  • 它不能跳到任何 forbidden 数组中的位置。

跳蚤可以往前跳 超过 它的家的位置,但是它 不能跳到负整数 的位置。

给你一个整数数组 forbidden ,其中 forbidden[i] 是跳蚤不能跳到的位置,同时给你整数 abx ,请你返回跳蚤到家的最少跳跃次数。如果没有恰好到达 x 的可行方案,请你返回 -1

示例 1:

输入:forbidden = [14,4,18,1,15], a = 3, b = 15, x = 9
输出:3
解释:往前跳 3 次(0 -> 3 -> 6 -> 9),跳蚤就到家了。

示例 2:

输入:forbidden = [8,3,16,6,12,20], a = 15, b = 13, x = 11
输出:-1

示例 3:

输入:forbidden = [1,6,2,14,5,17,4], a = 16, b = 9, x = 7
输出:2
解释:往前跳一次(0 -> 16),然后往回跳一次(16 -> 7),跳蚤就到家了。

提示:

  • 1 <= forbidden.length <= 1000
  • 1 <= a, b, forbidden[i] <= 2000
  • 0 <= x <= 2000
  • forbidden 中所有位置互不相同。
  • 位置 x 不在 forbidden 中。

方法:广度优先搜索

思路

求最短路径一般需要用广度优先搜索,但是此题中的图是个无限图,如果不限制搜索的范围,无法处理无解的情况。因此,解决此题的关键是找出搜索的范围,其中下限已经由题目给出,不能跳到负整数的位置,我们还需要找出搜索的上限,下面分情况讨论:

  1. a = b。此时为了次数最少,跳蚤没有必要向后跳,只需要一直往前跳。当它超过 x 却没有遇到 x,表示它再也跳不到 x 了,此时的上限可以设置为 x。
  2. a > b。题目规定,跳蚤不能连续往后跳 2 次,因此这只跳蚤运动轨迹中,任意连续的两次跳跃,总的行程一定是在前进的,前进了 a−ba-ba−b 的距离。即使它某一步是在后退,这一步的前一步和后一步(如果有的话)一定是在前进。此时跳蚤运动的上限为 x + b,在这个上限的情况下,跳蚤往回跳一步可以到达 x。在大于这个上限的情况下,即使跳蚤马上往回跳一步,所处的位置也大于 x,而且跳蚤接下来前进的次数必然会大于等于后退的次数,再也无法到达 x。因此在这种情况下,上限为 x + b。
  3. a < b。在这种情况下,上限为 max⁡(max⁡(forbidden) + a + b, x)。接下来证明这一点。为了方便,记 max⁡(forbidden) = f。首先,需要将数轴上大于等于 0 的位置分为三个区域:
    • [0, f],禁止区。所有 forbidden 中的位置都位于这个区域。
    • (f, max⁡(f + a + b, x)],安全区,它的右边界是 a < b 情况下我们想要证明的广度优先搜索的上限。
    • (max⁡(f + a + b, x), +∞) ,界外区。

这三个区域合起来组成了数轴上大于等于 0 的所有部分,注意 x 可能位于禁止区或者安全区,但不会是 forbidden 数组中的元素。假设某个步数最少的路径中,点 C 是第一个进入界外区(前进进入)的点,而点 H 是第一个离开界外区(后退离开)的点。因为 x 只可能位于禁止区或者安全区,因此如果这条路径存在点 C,那么必然存在点 H。如下图,横坐标为步数,纵坐标为与原点的距离。箭头朝右上表示前进,箭头朝右下表示后退。
1

接下来,我们通过交换线段 BC 和线段 GH ,并保持其他线段的的方向不变,来使得点 C 不再位于界外区。如下图,线段 BC’ 变为后退而线段 G’H 变为前进。

2

我们从以下几个方面论证这种交换的可行性:

  • 交换前,点 C,D,…,F,G 全都位于界外区,与原点的距离大于 f + a + b 。通过交换,这些点与原点的距离缩小了 a + b ,仍然大于 f。因此,这些点不会落到 forbidden 中。
  • 交换后不会增加这个路径的步数,也不会影响点 H 之后的点的位置。
  • 交换不会造成两次倒退。交换后,前进的线段 BC 变为后退的线段 BC’ ,但是 BC’ 的前一段 AB 一定是前进的。可以利用反证法证明,如果 AB 是后退的,那么点 A 就会在界外区,因为 a < b ,这样的话点 C 就不会是第一个界外区的点,因此 AB 一定是前进的。BC’ 的后一段 C’D’ 一定也是前进的。这里需要分为两种情况:
    • CD 原本就是前进的,那么 C’D’ 会保持原来前进的方向。通过交换,我们不会造成两次倒退。
    • CD 原本是后退的,那么点 D 就是我们前面讨论的第一个离开界外区的点 H,因为 a < b。这样一来,我们其实是交换了前进的 BC 和后退的 CD,得到了后退的 BC’ 和前进的 C’D,仍然不会造成两次倒退。

通过这样的交换,我们使得一个有效路径第一个进入界外区的点,不再位于界外区。新的路径,第一个进入界外区的点,可能位于点 C 和点 H 之间,也可能位于点 HHH 之后,也可能不存在这样的点。总之,我们可以不停地寻找第一个进入界外区的点,然后经过上述的交换,使得最终的路径的所有点都位于禁止区和安全区。这样,我们就证明出,如果某个输入有解,那么至少有一条最短路径,它的所有点都处于上限 max⁡(f + a + b, x) 之内。因此在这种情况下,上限为 max⁡(max⁡(forbidden) + a + b, x)。

综合以上三种情况,广度优先搜索的上限是 max⁡(max⁡(forbidden) + a, x) + b 。

在进行广度优先搜索时,除了需要注意到上下限,不能达到 forbidden 数组中的坐标,还需要注意到达每个坐标时,都会有前进到达还是后退到达两种状态。如果是前进到达时,下一步可以选择前进或者后退;如果是后退到达时,下一步只能选择前进。因此广度优先搜索的每个元素,需要保存三个信息,坐标,方向和步数。在代码中,我们用 1 表示前进, −1 表示后退,用哈希集合 visited 来记录已经达到过的位置和方向状态。在搜索的过程中,如果坐标第一次为 x,则返回当前步数。当队列为空时,表示 x 不可到达,返回 −1。

代码:

class Solution {
public:
    int minimumJumps(vector<int>& forbidden, int a, int b, int x) {
        queue<tuple<int, int, int>> q;
        unordered_set<int> visited;
        q.emplace(0, 1, 0);
        visited.emplace(0);
        int lower = 0, upper = max(*max_element(forbidden.begin(), forbidden.end()) + a, x) + b;
        unordered_set<int> forbiddenSet(forbidden.begin(), forbidden.end());
        while (!q.empty()) {
            auto [position, direction, step] = q.front();
            q.pop();
            if (position == x) {
                return step;
            }
            int nextPosition = position + a;
            int nextDirection = 1;
            if (lower <= nextPosition && nextPosition <= upper && !visited.count(nextPosition * nextDirection) && !forbiddenSet.count(nextPosition)) {
                visited.emplace(nextPosition * nextDirection);
                q.emplace(nextPosition, nextDirection, step + 1);
            }
            if (direction == 1) {
                nextPosition = position - b;
                nextDirection = -1;
                if (lower <= nextPosition && nextPosition <= upper && !visited.count(nextPosition * nextDirection) && !forbiddenSet.count(nextPosition)) {
                    visited.emplace(nextPosition * nextDirection);
                    q.emplace(nextPosition, nextDirection, step + 1);
                }
            }
        }
        return -1;
    }
};

时间 32ms 击败 44.76%使用 C++ 的用户
内存 18.11MB 击败 43.81%使用 C++ 的用户
复杂度分析

  • 时间复杂度:O(max⁡(max⁡(forbidden)+a,x)+b)。表达式为广度优先搜索的位置上限,每个位置最多会被计算两次。
  • 空间复杂度:O(max⁡(max⁡(forbidden)+a,x)+b)。表达式为广度优先搜索的位置上限,是队列和哈希集合的空间复杂度。
    author:力扣官方题解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/96662.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++中为什么有模板的函数不能和.h文件分离,即分别声明和定义

目录 1.查看问题 2.探索问题 3.解决问题 1.查看问题 1.先看下面三个文件 stack.h stack.cpp test.cpp 2.探索问题 有了解的小伙伴应该知道大概率是在预处理&#xff0c;编译&#xff0c;汇编&#xff0c;链接中编译环节出错了&#xff0c;它在其他文件中无法通过定义找到函…

MATLAB 2023安装方法之删除旧版本MATLAB,安装新版本MATLAB

说明&#xff1a;之前一直使用的是MATLAB R2020b&#xff0c;但最近复现Github上的程序时&#xff0c;运行不了&#xff0c;联系作者说他的程序只能在MATLAB 2021之后的版本运行&#xff0c;因此决定安装最新版本的MATLAB。 系统&#xff1a;Windows 11 需要卸载的旧MATLAB 版…

快手Java一面,全是基础

现在已经到了面试招聘比较火热的时候&#xff0c;准备面试的过程中&#xff0c;一定要多看面经&#xff0c;多自测&#xff01; 今天分享的是一位贵州大学的同学分享的快手一面面经。 快手一面主要会问一些基础问题&#xff0c;也就是比较简单且容易准备的常规八股&#xff0…

微信小程序云开发-云存储文件ID转http

一、前言 云开发的云储存文件默认是以cloudID的形式读取的&#xff0c;但是这种读取方式只能在微信小程序或内嵌H5中使用。 所以如果需要在其他地方使用&#xff0c;例如浏览器或网站等其他端读取文件的时候&#xff0c;需要转换成普通的http链接。 目前官方提供有转换的接口…

docker之Compose与DockerSwarm

目录 Compose 简介 概念 为什么需要&#xff1f; 配置字段 常用命令 安装 1.下载 2.授权 使用 1.创建文件 2.启动 docker Swarm 关键概念 调度策略 spread binpack random 特性 集群部署 1.准备 2.创建swarm并添加节点 在主服务器上创建swarm集群 节点…

8天长假快来了,Python分析【去哪儿旅游攻略】数据,制作可视化图表

目录 前言环境使用模块使用数据来源分析 代码实现导入模块请求数据解析保存 数据可视化导入模块、数据年份分布情况月份分布情况出行时间情况费用分布情况人员分布情况 前言 2023年的中秋节和国庆节即将来临&#xff0c;好消息是&#xff0c;它们将连休8天&#xff01;这个长假…

MongoDB入门

简介 MongoDB是一个开源、高性能、支持海量数据存储的文档型数据库 是NoSQL数据库产品中的一种&#xff0c;是最像关系型数据库&#xff08;MySQL&#xff09;的非关系型数据库 内部采用BSON(二进制JSON)格式来存储数据,并支持水平扩展。 MongoDB本身并不是完全免费的,它对于…

算法-图BFS/DFS-单词接龙

算法-图BFS/DFS-单词接龙 1 题目概述 1.1 题目出处 https://leetcode-cn.com/problems/number-of-islands 1.2 题目描述 给定两个单词&#xff08;beginWord 和 endWord&#xff09;和一个字典&#xff0c;找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如…

C++八股记录

C内存管理 C中&#xff0c;内存分成5个区。 栈&#xff1a;函数内局部变量&#xff1b;自动管理&#xff0c;效率高&#xff0c;但空间较小&#xff1b; 堆&#xff1a;new分配的内存块&#xff1b;手动管理&#xff0c;效率低&#xff0c;但空间大&#xff1b; 自由存储区&…

代码复现,我能行之DMP-MATLAB

代码复现&#xff0c;我能行——系列一 一、基础概念 Dynamic Movement Primitives &#xff08;DMP&#xff09;&#xff0c;中文为动态运动基元或动态运动原语&#xff0c;由美国University of Southern California的Stefan Schaal教授团队于2002年提出&#xff0c;是一种用…

2023年智慧政务一网通办云平台顶层设计与建设方案PPT

导读:原文《2023年智慧政务一网通办云平台顶层设计与建设方案PPT》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 部分内容:

计算机竞赛 基于Django与深度学习的股票预测系统

文章目录 0 前言1 课题背景2 实现效果3 Django框架4 数据整理5 模型准备和训练6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于Django与深度学习的股票预测系统 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff…

GIT 常用指令

基础指令 $ git init #初始化仓库&#xff0c;在该文件夹创建的为workspace$ git add . #已暂存 [.通配符&#xff0c;全部添加]$ git commit -m "log add file" #提交到仓库,并写了日志 ”log add file“$ git status #查看状态&#xff0c;可查看被修改的文件…

win11出现安全中心空白和IT管理员已限制对此应用的某些区域的访问

问题 windows安全中心服务被禁用 winr 输入services.msc 找到windows安全中心服务查看是否被禁用&#xff0c;改为启动&#xff0c;不可以改动看第三条 打开设置&#xff0c;找到应用—windows安全中心–终止–修复–重置 重启如果还是不行看第四条 家庭版系统需要打开gped…

新手指南:7个步骤制定成功的项目预算

每个项目都涉及成本。项目越大、越复杂&#xff0c;执行的时间和金钱成本就越高。企业不会拥有无限的资源&#xff0c;所以每个项目都需要项目预算。 但挑战在于&#xff1a;确定项目需要多少预算并不总是那么容易。低估需求&#xff0c;最终会导致人手短缺&#xff0c;无法按…

数组中出现次数超过一半的数字

⭐️ 题目描述 &#x1f31f; OJ链接&#xff1a;数组中出现次数超过一半的数字 思路&#xff1a; 采用投票计数的方式&#xff0c;我们可以把每个数字都看成一次投票并且计数&#xff0c;那么最后剩下来的就是数组中数字出现次数最多的那一个。比如 { 1,2,3,2,2,2,5,4,2 } &a…

《动手学深度学习》-57长短期记忆网络LSTM

沐神版《动手学深度学习》学习笔记&#xff0c;记录学习过程&#xff0c;详细的内容请大家购买书籍查阅。 b站视频链接 开源教程链接 长短期记忆网络&#xff08;LSTM&#xff09; 长期以来&#xff0c;隐变量模型存在长期信息保存和短期输入缺失的问题。解决这一问题的最早…

【C# Programming】编程入门:数组、操作符、控制流

目录 一、数组 1、数组的声明 1.1 一维数组声明&#xff1a; 1.2 多维数组声明&#xff1a; 2、数组的实例化和赋值 2.1 数组在声明时通过在花括号中使用以逗号分隔的数据项对数组赋值&#xff0c; 例如&#xff1a; 2.2 如果在声明后赋值&#xff0c;则需…

算法通过村第四关-栈青铜笔记|手写栈操作

文章目录 前言1. 栈的基础概要1.1 栈的特征1.2 栈的操作1.3 Java中的栈 2. 栈的实现&#xff08;手写栈&#xff09;2.1 基于数组实现2.2 基于链表实现2.3 基于LinkedList实现 总结 前言 提示&#xff1a;我自己一个人的感觉很好 我并不想要拥有你 除非你比我的独处更加宜人 --…

探索生成式人工智能的前景

一、什么是生成式人工智能&#xff1f; 生成式人工智能&#xff08;Generative AI&#xff09;是一类人工智能&#xff08;AI&#xff09;技术和模型&#xff0c;旨在创建新颖的内容。与简单的复制不同&#xff0c;这些模型通过利用从训练数据集中收集到的模式和见解&#xff…