1049.困于环中的机器人(Java/Go)|LeetCode刷题笔记

171 阅读4分钟

1049.困于环中的机器人

官方题目描述

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

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

机器人可以接受下列三条指令之一: "G":直走 1 个单位 "L":左转 90 度 "R":右转 90 度 机器人按顺序执行指令 instructions,并一直重复它们。

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

初读题目,比较容易想到的点是:
1.当机器人在一次指令后停在(0,0)时肯定永远无法离开
2.当一次指令后不在原地且不变方向时一定可以一路向指定方向离开
其实这两个条件已经足够完成这个题了
但我一开始没有想到,我还在想当机器人不在原地且改变了方向时,该如何判断
于是带着疑问继续读示例

官方示例

示例 1:

输入: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:

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

示例 3:

输入: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.假设一个机器人在一次指令后离开了原地且与起始方向(北)相反,也就是向南
那么机器人再执行一次一定是会原路返回的,也就是每两次指令后回到原点,机器人陷入回环!

2.东与西可以视为同一种情况,它们都和起始方向呈90度,一段指令带来的路程无论如何曲折都只会是起始点和终点两个点,那么可以将其简化为一条线段,如果将其简化为线段,那么机器人每四次指令就一定会回到原点,陷入回环!
发散一下,如果机器人收到的指令不是90度转弯,那机器人回到原点所需的指令数应该等于:360/每次转弯的角度。
不再迷惑了,开始编码!

我的初次解题(Java)

初次编码选择了自己最熟悉的Java,这一定是不够优秀的写法,时间复杂度可以,但空间复杂度可就不堪入目了

public boolean isRobotBounded(String instructions) {
    int x = 0,y = 0;
    //方向顺序为北东南西
    int direction = 0;
    int length = instructions.length();
    for (int i = 0; i < length ; i++) {
        switch (instructions.charAt(i)){
            case 'G':
                switch (direction){
                    case 0:
                        y += 1;
                        break;
                    case 1:
                        x += 1;
                        break;
                    case 2:
                        y -= 1;
                        break;
                    case 3:
                        x -= 1;
                        break;
                    default:
                        break;
                }
                break;
            case 'L':
                // -1+4
                direction = (direction + 3) %4;
                break;
            case 'R':
                direction = (direction + 1) %4;
                break;
            default:
                break;
        }
    }
    return direction != 0 || (x == 0 && y == 0) ;
}

学习官方题解思路并做出一定优化

public boolean isRobotBounded(String instructions) {
    int[][] direc = {{0,1},{1,0},{0,-1},{-1,0}};
    int x = 0,y = 0;
    //方向顺序为北东南西
    int direction = 0;
    int length = instructions.length();
    for (int i = 0; i < length ; i++) {
        switch (instructions.charAt(i)){
            case 'G':
                x += direc[direction][0];
                y += direc[direction][1];
                break;
            case 'L':
                // -1+4
                direction = (direction + 3) %4;
                break;
            case 'R':
                direction = (direction + 1) %4;
                break;
            default:
                break;
        }
    }
    return direction != 0 || (x == 0 && y == 0) ;
}
企业微信截图_20230413140702.png

官方给出的题解使用的是ifelse,理论上我用switch是空间换时间,但结果空间还低了一些,很神奇

Go解法

最近在学习Go语言,也就顺带用Go再写一遍

func isRobotBounded(instructions string) bool {
   direc := [][]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}
   x, y := 0, 0
   direction := 0
   length := len(instructions)
   for i := 0; i < length; i++ {
      switch instructions[i] {
      case 'G':
         x += direc[direction][0]
         y += direc[direction][1]
         break
      case 'L':
         direction = (direction + 3) % 4
         break
      case 'R':
         direction = (direction + 1) % 4
         break
      default:
         break
      }
   }
   return direction != 0 || (x == 0 && y == 0)
}

至此,感谢阅读!