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) ;
}
官方给出的题解使用的是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)
}
至此,感谢阅读!