LeetCode 1041.困于环中的机器人

一.题目

在无限的平面上,机器人最初位于 (0, 0) 处,面朝北方。注意:

  • 北方向 是y轴的正方向。
  • 南方向 是y轴的负方向。
  • 东方向 是x轴的正方向。
  • 西方向 是x轴的负方向。

机器人可以接受下列三条指令之一:

  • "G":直走 1 个单位
  • "L":左转 90 度
  • "R":右转 90 度

机器人按顺序执行指令 instructions,并一直重复它们。

只有在平面中存在环使得机器人永远无法离开时,返回 true。否则,返回 false

示例 1:

makefile 复制代码
输入: instructions = "GGLLGG"
输出: true
解释: 机器人最初在(0,0)处,面向北方。
"G":移动一步。位置:(0,1)方向:北。
"G":移动一步。位置:(0,2).方向:北。
"L":逆时针旋转90度。位置:(0,2).方向:西。
"L":逆时针旋转90度。位置:(0,2)方向:南。
"G":移动一步。位置:(0,1)方向:南。
"G":移动一步。位置:(0,0)方向:南。
重复指令,机器人进入循环:(0,0)------>(0,1)------>(0,2)------>(0,1)------>(0,0)。
在此基础上,我们返回true。

示例 2:

arduino 复制代码
输入: instructions = "GG"
输出: false
解释: 机器人最初在(0,0)处,面向北方。
"G":移动一步。位置:(0,1)方向:北。
"G":移动一步。位置:(0,2).方向:北。
重复这些指示,继续朝北前进,不会进入循环。
在此基础上,返回false。

示例 3:

makefile 复制代码
输入: instructions = "GL"
输出: true
解释: 机器人最初在(0,0)处,面向北方。
"G":移动一步。位置:(0,1)方向:北。
"L":逆时针旋转90度。位置:(0,1).方向:西。
"G":移动一步。位置:(- 1,1)方向:西。
"L":逆时针旋转90度。位置:(- 1,1)方向:南。
"G":移动一步。位置:(- 1,0)方向:南。
"L":逆时针旋转90度。位置:(- 1,0)方向:东方。
"G":移动一步。位置:(0,0)方向:东方。
"L":逆时针旋转90度。位置:(0,0)方向:北。
重复指令,机器人进入循环:(0,0)------>(0,1)------>(- 1,1)------>(- 1,0)------>(0,0)。
在此基础上,我们返回true。

提示:

  • 1 <= instructions.length <= 100
  • instructions[i] 仅包含 'G', 'L', 'R'

二.解析

leetcode.cn/problems/ro...

思路是和官方一样的,结论就是第一轮结束时,如果在原地或者方向不是北,那么平面就存在环,机器人无法离开,return true,只有不在原地且最终方向是北(即起始方向) return false

写法一:

在实现上,第一想法比较直观,首先开一个 direction : stepNumber 的object,并记录当前方向

js 复制代码
const directionAndStep = {
    N: 0,
    W: 0,
    S: 0,
    E: 0,
  };
let currentDirection = "N";

然后遍历instructions,每次到了G要走动就把stepNumber + 1, L或者R就改变currentDirection

js 复制代码
for (const instruction of instructions) {
        // 如果是G,当前方向step + 1
        if (instruction === "G") directionAndStep[currentDirection]++;
        else {
            // L 或者 G,就获取改变后的方向
            currentDirection = nextDirection(instruction);
        }
    }

这里写了一个函数nextDirection用于把L/G按当前方向转换成下一步的方向

js 复制代码
function nextDirection(dir) {
        const keys = Object.keys(directionAndStep);
        let diff;
        if (dir === "L") diff = 3;
        if (dir === "R") diff = 1;
        const idx = keys.indexOf(currentDirection);
        return keys[(idx + diff) % keys.length];
    }

再然后计算当前x,y轴的行进step,以W,N为正方向,用于判断是否在原点,如果在原点则有环,return true

js 复制代码
    const x = directionAndStep["W"] - directionAndStep["E"];
    const y = directionAndStep["N"] - directionAndStep["S"];
    if (x === 0 && y === 0) return true;

最后就是如果不在原点的话,如果方向是起始方向,就无环可以出的去,return false,其他的都出不去

js 复制代码
    if (currentDirection === "N") return false;
    else return true;

完整代码如下:

js 复制代码
/**
 * @param {string} instructions
 * @return {boolean}
 */
var isRobotBounded = function (instructions) {
    // 维护一个记录每个方向步数的object
    const directionAndStep = {
        N: 0,
        W: 0,
        S: 0,
        E: 0
    };
    // 记录当前方向
    let currentDirection = "N";
    // L 或者 R时,转向的方向
    function nextDirection(dir) {
        const keys = Object.keys(directionAndStep);
        let diff;
        if (dir === "L") diff = 3;
        if (dir === "R") diff = 1;
        const idx = keys.indexOf(currentDirection);
        return keys[(idx + diff) % keys.length];
    }
    for (const instruction of instructions) {
        // 如果是G,当前方向step + 1
        if (instruction === "G") directionAndStep[currentDirection]++;
        else {
            // L 或者 G,就获取改变后的方向
            currentDirection = nextDirection(instruction);
        }
    }
    // 计算当前x,y轴的行进step,以W,N为正方向
    const x = directionAndStep["W"] - directionAndStep["E"];
    const y = directionAndStep["N"] - directionAndStep["S"];
    // 如果还在原点,那么永远无法离开
    if (x === 0 && y === 0) return true;
    // 如果不在原点,只有方向是N才能离开
    if (currentDirection === "N") return false;
    else return true;

};

写法二:

思索一下,既然我们计算了x,y轴,对于robot的坐标,为什么还要算四个方向呢?变成两个方向不就好了?用数字代替方向,也更好写

js 复制代码
/**
 * @param {string} instructions
 * @return {boolean}
 */
var isRobotBounded = function (instructions) {
    // N -> 0, E -> 1, S -> 2, W -> 3
    let directionIndex = 0;
    // robot 的坐标
    let coordinates = [0, 0];
    for(const instruction of instructions){
        if(instruction === "G"){
            // 按方向移动robot的坐标
            if(directionIndex === 0) coordinates[1]++;
            else if(directionIndex === 1) coordinates[0]++;
            else if(directionIndex === 2) coordinates[1]--;
            else if(directionIndex === 3) coordinates[0]--;
        }else if(instruction === "R"){
            // 按方向变动directionIndex
            directionIndex += 1;
            directionIndex %= 4;
        }else if(instruction === "L"){
            // 按方向变动directionIndex
            directionIndex += 3;
            directionIndex %= 4;
        }
    }
    return !(directionIndex === 0 && (coordinates[0] || coordinates[1]))
};

当然两种写法的思路是一样的,写法二会更加优雅一些。

以上

相关推荐
hh随便起个名1 天前
力扣二叉树的三种遍历
javascript·数据结构·算法·leetcode
Dingdangcat861 天前
城市交通多目标检测系统:YOLO11-MAN-FasterCGLU算法优化与实战应用_3
算法·目标检测·目标跟踪
tang&1 天前
滑动窗口:双指针的优雅舞步,征服连续区间问题的利器
数据结构·算法·哈希算法·滑动窗口
拼命鼠鼠1 天前
【算法】矩阵链乘法的动态规划算法
算法·矩阵·动态规划
LYFlied1 天前
【每日算法】LeetCode 17. 电话号码的字母组合
前端·算法·leetcode·面试·职场和发展
式5161 天前
线性代数(八)非齐次方程组的解的结构
线性代数·算法·机器学习
橘颂TA1 天前
【剑斩OFFER】算法的暴力美学——翻转对
算法·排序算法·结构与算法
叠叠乐1 天前
robot_state_publisher 参数
java·前端·算法
hweiyu001 天前
排序算法:冒泡排序
算法·排序算法
brave and determined1 天前
CANN训练营 学习(day9)昇腾AscendC算子开发实战:从零到性能冠军
人工智能·算法·机器学习·ai·开发环境·算子开发·昇腾ai