Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LeetCode题解:874. 模拟行走机器人,模拟情境,JavaScript,详细注释 #234

Open
chencl1986 opened this issue Dec 5, 2020 · 0 comments

Comments

@chencl1986
Copy link
Owner

原题链接:https://leetcode-cn.com/problems/walking-robot-simulation/

解题思路:

参考了图解【模拟行走机器人】

  1. 明确题意:
    • 需要计算的是机器人所有经过的路径点的最大欧式距离的平方。也就是说,如果当前命令是让机器人行走4,机器人会走过1、2、3、4,一共4个位置,每个位置都要计算。
    • 欧式距离的平方,指的是当前坐标到原点(0,0)的距离的平方。
  2. 如何控制机器人方向:
    • X轴使用数组directionX = [0, 1, 0, -1]表示方向。
    • Y轴使用数组directionY = [1, 0, -1, 0]表示方向。
    • 数组中的1,表示向当前指示的方向行走一步,正负表示在坐标轴的方向是正向还是负向。
    • 使用索引direction来表示当前前进方向。
    • 初始状态为向北,对应在坐标轴的方向为Y轴正向,即两个数组的索引都为0。
    • 从初始状态向左旋转,就是从Y轴正向,转为X轴负向,对应的索引为3。因此如果要控制机器人向左旋转,只要将当前索引加3。
    • 从初始状态向右旋转,就是从Y轴正向,转为X轴正向,对应的索引为1。因此如果要控制机器人向右旋转,只要将当前索引加1。
  3. 如何控制机器人行走:
    • 我们实际上无需描绘机器人的行走路径,只需要知道当前机器人所在的坐标x, y,即可计算欧氏距离的平方。因此行走就转换为计算当前坐标。
    • 如果接收到行走命令为4,即为机器人行走4次,每次都在当前方向行走1。
    • 如果当前方向为北,对应方向索引为0,可在数组中查找到directionX[0]为0,directionY[0]为1,即可表示向Y轴行走1。
    • 因此新坐标的计算方式为为:
    const newX = x + directionX[direction];
    const newY = y + directionY[direction];
    
  4. 如何判断机器人是否遇到障碍物:
    • 障碍物不止一个,并且分布在地图中的各处,因此每走一步都要判断所有障碍点。
    • 可以将障碍物都存储在Set中,行走时先计算预计达到的坐标,并判断该坐标是否存在于Set中。
    • 如果是不存在,才将newX, newY更新到x, y中,作为新坐标。如果存在则不更新,机器人自动停止在了障碍物之前位置x, y
/**
 * @param {number[]} commands
 * @param {number[][]} obstacles
 * @return {number}
 */
var robotSim = function (commands, obstacles) {
  // 机器人行走方向
  // 存储X轴方向以及行走的步数,1表示向X轴正方向走一步,-1表示X轴负方向走一步
  const directionX = [0, 1, 0, -1];
  // 存储Y轴方向,1表示Y轴正方向走一步,-1表示Y轴负方向走一步
  const directionY = [1, 0, -1, 0];
  // 缓存方向数组的长度,用于确定转向操作后取余
  const directionLength = directionX.length;
  // 用于表示当前的前进方向,是directionX和directionY的索引
  // 例如direction为0,选中directionX[0]为0,directionY[0]为1
  // 表示当前行走方向向是Y轴正向,即向北
  let direction = 0;

  // 机器人当前位置坐标
  let x = 0;
  let y = 0;

  // 最大欧氏距离的平方
  let maxDistance = 0;

  // 由于每走一步,需要判断是否遇到任何一个障碍点,因此使用Set保存所有障碍点,用于快速判断
  // 如果要走的点坐标与障碍物坐标重合,即为遇到障碍物
  let obstacleSet = new Set(obstacles.map((obstacle) => obstacle.toString()));

  // 遍历每个命令,按照命令指导机器人行动
  for (const command of commands) {
    if (command === -2) {
      // 机器人向左旋转90度,进行取余操作,避免索引超出数组长度
      direction = (direction + 3) % directionLength;
    } else if (command === -1) {
      // 机器人向右旋转90度
      direction = (direction + 1) % directionLength;
    } else {
      // 向前移动时,每次移动一步,便于判断是否移动到障碍点
      for (let i = 0; i < command; i++) {
        // 计算新的X轴和Y轴坐标,需要在判断是否与障碍物从何后,再决定是否行走
        // 根据direction索引,选取方向数组中的相应方向的步数,确定下一个点的坐标
        const newX = x + directionX[direction];
        const newY = y + directionY[direction];
        // 计算用于对比是否障碍点的key
        const newPointKey = `${newX},${newY}`;

        // 如果新坐标存在与Set中,表示当前坐标与障碍物重合,不可以继续行走
        if (obstacleSet.has(newPointKey)) {
          // 退出循环,即为终止行走,即停留在障碍物之前的点上
          // 由于上一步行走时,欧式距离的平方已经计算过,在此无需计算
          break;
        } else {
          // 将机器人行走到新坐标
          x = newX;
          y = newY;
          // 计算当前欧式距离的平方
          const distance = x * x + y * y;
          // 计算最大欧氏距离的平方
          maxDistance = Math.max(distance, maxDistance);
        }
      }
    }
  }

  return maxDistance;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant