模拟行走机器人
字数 3487 2025-12-23 04:12:48

模拟行走机器人

题目描述

你在一个无限大的网格上,从 (0, 0) 点开始,面朝北方。机器人可以接收三种指令:

  1. -2:向左转 90 度。
  2. -1:向右转 90 度。
  3. 1 <= x <= 9:沿当前方向前进 x 个单位长度。

此外,网格上还有一些障碍物。机器人在前进过程中,如果下一个移动的目标格子存在障碍物,它将停在障碍物前一个格子(即不会踏上障碍物),并继续执行下一条指令。

给定一个包含障碍物坐标的数组 obstacles 和一个指令数组 commands,请你计算机器人执行完所有指令后,距离原点的最大欧式距离(即 sqrt(x^2 + y^2))。注意只需要计算整个过程中的最大距离,而不是最终距离。

示例:
输入:commands = [4, -1, 4, -2, 4], obstacles = [[2, 4]]
输出:65
解释:机器人的路径如下:

  1. 前进4个单位到 (0, 4)。
  2. 向右转,面朝东方。
  3. 前进4个单位,但遇到障碍物 (2, 4)(因为目标格子 (4, 4) 需要经过 (1,4),(2,4),(3,4),(4,4),其中(2,4)是障碍),所以停在障碍物前一个格子,即 (1, 4)。
  4. 向左转,面朝北方。
  5. 前进4个单位到 (1, 8)。
    整个过程距离原点的最远距离是 1^2 + 8^2 = 65

解题过程

步骤一:问题理解与核心难点

这个题目的核心是模拟机器人的行走过程,并在模拟中处理障碍物。难点在于:

  1. 方向变化:如何高效地表示和处理“左转”、“右转”带来的方向变化。
  2. 障碍物检测:机器人是一步一步移动的,但指令 x 可能意味着连续移动多步。在每一步移动前,都必须检查前方目标格子是否是障碍物。如果使用朴素方法,每次都在 obstacles 列表中线性查找,时间复杂度会很高。
  3. 距离计算:只需要记录过程中的最大欧式距离的平方即可(因为比较大小不需要开方)。

步骤二:数据结构选择

为了高效检测障碍物,我们需要将障碍物的坐标存储在一个能快速查询的数据结构中。由于网格坐标是整数对 (x, y),我们可以使用哈希集合HashSetSet)来存储。

  • 我们将每个障碍物的坐标 (x, y) 转换为一个唯一的字符串(如 “x,y”)或一个长整型(如 ((long)x << 32) | ((long)y & 0xffffffffL))作为键存入集合。
  • 这样,判断一个坐标是否是障碍物,其时间复杂度可以降至平均 O(1)。

为什么选择哈希集合?
因为我们需要频繁执行 contains 操作来检查某个坐标是否是障碍物。哈希表的平均 O(1) 查找时间远优于数组的线性查找 O(n) 或排序后二分查找 O(log n)。

步骤三:方向表示与移动向量

机器人有四个方向:北(N),东(E),南(S),西(W)。我们可以用一个数组来表示这四个方向。

  • 定义方向数组:dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]]
    • [0, 1]:向北移动(x不变,y增加)
    • [1, 0]:向东移动(x增加,y不变)
    • [0, -1]:向南移动(x不变,y减少)
    • [-1, 0]:向西移动(x减少,y不变)
  • 我们用一个索引 dirIndex(初始为0)来记录当前方向。它对应 dirs 数组的索引。
    • dirIndex = 0:面朝北方。
    • 右转(-1):dirIndex = (dirIndex + 1) % 4。例如,从北(0)转到东(1)。
    • 左转(-2):dirIndex = (dirIndex - 1 + 4) % 4。例如,从北(0)转到西(3)。

这样,方向变换就变成了简单的索引运算。

步骤四:模拟流程算法步骤

  1. 初始化

    • 当前位置 x = 0, y = 0
    • 当前方向索引 dirIndex = 0(向北)。
    • 最大距离平方 maxDistSq = 0
    • 将障碍物列表 obstacles 中的所有坐标转换为字符串(或长整型)并存入一个哈希集合 obstacleSet
  2. 处理每条指令

    • 如果指令是 -1dirIndex = (dirIndex + 1) % 4
    • 如果指令是 -2dirIndex = (dirIndex - 1 + 4) % 4
    • 如果指令是正整数 steps
      • 获取当前方向的移动向量:[dx, dy] = dirs[dirIndex]
      • 循环 steps 次:
        • 计算下一个目标位置:nextX = x + dx, nextY = y + dy
        • 如果 (nextX, nextY)obstacleSet 中:
          • 说明是障碍物,停止本次移动,不更新 (x, y),并跳出本次 steps 循环。
        • 否则(不是障碍物):
          • 更新当前位置:x = nextX, y = nextY
          • 计算当前距离原点的平方:currentDistSq = x*x + y*y
          • 更新最大距离:maxDistSq = max(maxDistSq, currentDistSq)
  3. 返回结果

    • 所有指令执行完毕后,返回 maxDistSq

步骤五:举例详解(使用题目示例)

输入:commands = [4, -1, 4, -2, 4], obstacles = [[2, 4]]

  1. 初始化:(x, y) = (0, 0), dirIndex = 0 (北), maxDistSq = 0, obstacleSet = {“2,4”}
  2. 指令 4 (向北走4步):
    • 方向向量 [0, 1]
    • 第1步:next(0,1) 不在障碍集,移动至 (0,1)maxDistSq = max(0, 1) = 1
    • 第2步:next(0,2) 不在障碍集,移动至 (0,2)maxDistSq = max(1, 4) = 4
    • 第3步:next(0,3) 不在障碍集,移动至 (0,3)maxDistSq = max(4, 9) = 9
    • 第4步:next(0,4) 不在障碍集,移动至 (0,4)maxDistSq = max(9, 16) = 16
  3. 指令 -1 (右转):dirIndex = (0 + 1) % 4 = 1 (东)。
  4. 指令 4 (向东走4步):
    • 方向向量 [1, 0]
    • 第1步:next(1,4) 不在障碍集,移动至 (1,4)maxDistSq = max(16, 17) = 17
    • 第2步:next(2,4) 障碍集!停止移动,当前位置保持在 (1,4)
  5. 指令 -2 (左转):dirIndex = (1 - 1 + 4) % 4 = 0 (北)。
  6. 指令 4 (向北走4步):
    • 方向向量 [0, 1]
    • 第1步:next(1,5) 不在障碍集,移动至 (1,5)maxDistSq = max(17, 26) = 26
    • 第2步:next(1,6) 不在障碍集,移动至 (1,6)maxDistSq = max(26, 37) = 37
    • 第3步:next(1,7) 不在障碍集,移动至 (1,7)maxDistSq = max(37, 50) = 50
    • 第4步:next(1,8) 不在障碍集,移动至 (1,8)maxDistSq = max(50, 65) = 65
  7. 返回 maxDistSq = 65

步骤六:复杂度分析

  • 时间复杂度:O(N + K),其中 N 是 commands 指令总数(注意每个移动指令会拆解成一步步执行,总步数不超过 9N),K 是障碍物数量。构建哈希集合 O(K),模拟过程 O(N)。
  • 空间复杂度:O(K),用于存储障碍物的哈希集合。

关键点总结

  1. 使用方向数组和索引是处理转向的简洁方法。
  2. 使用哈希集合存储障碍物坐标是实现高效检测的核心,它避免了在每一步移动时都遍历整个障碍物列表。
  3. 模拟时必须单步移动,并在每一步前检查障碍物,以确保在障碍物前停下。
  4. 结果只需返回过程中最大距离的平方,无需开方。
模拟行走机器人 题目描述 你在一个无限大的网格上,从 (0, 0) 点开始,面朝北方。机器人可以接收三种指令: -2 :向左转 90 度。 -1 :向右转 90 度。 1 <= x <= 9 :沿当前方向前进 x 个单位长度。 此外,网格上还有一些障碍物。机器人在前进过程中,如果下一个移动的目标格子存在障碍物,它将停在障碍物 前一个 格子(即不会踏上障碍物),并继续执行下一条指令。 给定一个包含障碍物坐标的数组 obstacles 和一个指令数组 commands ,请你计算机器人执行完所有指令后,距离原点的 最大欧式距离 (即 sqrt(x^2 + y^2) )。注意只需要计算整个过程中的最大距离,而不是最终距离。 示例: 输入: commands = [4, -1, 4, -2, 4] , obstacles = [[2, 4]] 输出:65 解释:机器人的路径如下: 前进4个单位到 (0, 4)。 向右转,面朝东方。 前进4个单位,但遇到障碍物 (2, 4)(因为目标格子 (4, 4) 需要经过 (1,4),(2,4),(3,4),(4,4),其中(2,4)是障碍),所以停在障碍物前一个格子,即 (1, 4)。 向左转,面朝北方。 前进4个单位到 (1, 8)。 整个过程距离原点的最远距离是 1^2 + 8^2 = 65 。 解题过程 步骤一:问题理解与核心难点 这个题目的核心是 模拟 机器人的行走过程,并在模拟中处理障碍物。难点在于: 方向变化 :如何高效地表示和处理“左转”、“右转”带来的方向变化。 障碍物检测 :机器人是一步一步移动的,但指令 x 可能意味着连续移动多步。在每一步移动前,都必须检查前方目标格子是否是障碍物。如果使用朴素方法,每次都在 obstacles 列表中线性查找,时间复杂度会很高。 距离计算 :只需要记录过程中的最大欧式距离的平方即可(因为比较大小不需要开方)。 步骤二:数据结构选择 为了高效检测障碍物,我们需要将障碍物的坐标存储在一个能快速查询的数据结构中。由于网格坐标是整数对 (x, y) ,我们可以使用 哈希集合 ( HashSet 或 Set )来存储。 我们将每个障碍物的坐标 (x, y) 转换为一个唯一的字符串(如 “x,y” )或一个长整型(如 ((long)x << 32) | ((long)y & 0xffffffffL) )作为键存入集合。 这样,判断一个坐标是否是障碍物,其时间复杂度可以降至平均 O(1)。 为什么选择哈希集合? 因为我们需要频繁执行 contains 操作来检查某个坐标是否是障碍物。哈希表的平均 O(1) 查找时间远优于数组的线性查找 O(n) 或排序后二分查找 O(log n)。 步骤三:方向表示与移动向量 机器人有四个方向:北(N),东(E),南(S),西(W)。我们可以用一个数组来表示这四个方向。 定义方向数组: dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]] [0, 1] :向北移动(x不变,y增加) [1, 0] :向东移动(x增加,y不变) [0, -1] :向南移动(x不变,y减少) [-1, 0] :向西移动(x减少,y不变) 我们用一个索引 dirIndex (初始为0)来记录当前方向。它对应 dirs 数组的索引。 dirIndex = 0 :面朝北方。 右转( -1 ): dirIndex = (dirIndex + 1) % 4 。例如,从北(0)转到东(1)。 左转( -2 ): dirIndex = (dirIndex - 1 + 4) % 4 。例如,从北(0)转到西(3)。 这样,方向变换就变成了简单的索引运算。 步骤四:模拟流程算法步骤 初始化 : 当前位置 x = 0 , y = 0 。 当前方向索引 dirIndex = 0 (向北)。 最大距离平方 maxDistSq = 0 。 将障碍物列表 obstacles 中的所有坐标转换为字符串(或长整型)并存入一个哈希集合 obstacleSet 。 处理每条指令 : 如果指令是 -1 : dirIndex = (dirIndex + 1) % 4 。 如果指令是 -2 : dirIndex = (dirIndex - 1 + 4) % 4 。 如果指令是正整数 steps : 获取当前方向的移动向量: [dx, dy] = dirs[dirIndex] 。 循环 steps 次: 计算下一个目标位置: nextX = x + dx , nextY = y + dy 。 如果 (nextX, nextY) 在 obstacleSet 中: 说明是障碍物,停止本次移动, 不更新 (x, y) ,并跳出本次 steps 循环。 否则(不是障碍物): 更新当前位置: x = nextX , y = nextY 。 计算当前距离原点的平方: currentDistSq = x*x + y*y 。 更新最大距离: maxDistSq = max(maxDistSq, currentDistSq) 。 返回结果 : 所有指令执行完毕后,返回 maxDistSq 。 步骤五:举例详解(使用题目示例) 输入: commands = [4, -1, 4, -2, 4] , obstacles = [[2, 4]] 初始化: (x, y) = (0, 0) , dirIndex = 0 (北), maxDistSq = 0 , obstacleSet = {“2,4”} 。 指令 4 (向北走4步): 方向向量 [0, 1] 。 第1步: next(0,1) 不在障碍集,移动至 (0,1) , maxDistSq = max(0, 1) = 1 。 第2步: next(0,2) 不在障碍集,移动至 (0,2) , maxDistSq = max(1, 4) = 4 。 第3步: next(0,3) 不在障碍集,移动至 (0,3) , maxDistSq = max(4, 9) = 9 。 第4步: next(0,4) 不在障碍集,移动至 (0,4) , maxDistSq = max(9, 16) = 16 。 指令 -1 (右转): dirIndex = (0 + 1) % 4 = 1 (东)。 指令 4 (向东走4步): 方向向量 [1, 0] 。 第1步: next(1,4) 不在障碍集,移动至 (1,4) , maxDistSq = max(16, 17) = 17 。 第2步: next(2,4) 在 障碍集!停止移动,当前位置保持在 (1,4) 。 指令 -2 (左转): dirIndex = (1 - 1 + 4) % 4 = 0 (北)。 指令 4 (向北走4步): 方向向量 [0, 1] 。 第1步: next(1,5) 不在障碍集,移动至 (1,5) , maxDistSq = max(17, 26) = 26 。 第2步: next(1,6) 不在障碍集,移动至 (1,6) , maxDistSq = max(26, 37) = 37 。 第3步: next(1,7) 不在障碍集,移动至 (1,7) , maxDistSq = max(37, 50) = 50 。 第4步: next(1,8) 不在障碍集,移动至 (1,8) , maxDistSq = max(50, 65) = 65 。 返回 maxDistSq = 65 。 步骤六:复杂度分析 时间复杂度 :O(N + K),其中 N 是 commands 指令总数(注意每个移动指令会拆解成一步步执行,总步数不超过 9N),K 是障碍物数量。构建哈希集合 O(K),模拟过程 O(N)。 空间复杂度 :O(K),用于存储障碍物的哈希集合。 关键点总结 : 使用方向数组和索引是处理转向的简洁方法。 使用哈希集合存储障碍物坐标是实现高效检测的核心 ,它避免了在每一步移动时都遍历整个障碍物列表。 模拟时必须 单步移动 ,并在每一步前检查障碍物,以确保在障碍物前停下。 结果只需返回过程中最大距离的平方,无需开方。