一、Problem
在无限的平面上,机器人最初位于 (0, 0) 处,面朝北方。机器人可以接受下列三条指令之一:
“G”:直走 1 个单位
“L”:左转 90 度
“R”:右转 90 度
机器人按顺序执行指令 instructions,并一直重复它们。
只有在平面中存在环使得机器人永远无法离开时,返回 true。否则,返回 false。
输入:"GGLLGG"
输出:true
解释:
机器人从 (0,0) 移动到 (0,2),转 180 度,然后回到 (0,0)。
重复这些指令,机器人将保持在以原点为中心,2 为半径的环中进行移动。
提示:
1 <= instructions.length <= 100
instructions[i] 在 {‘G’, ‘L’, ‘R’} 中
二、Solution
方法一:模拟
一开始的错误思路:用 set 存储每个座标点的字符串,如果再次遇到那么证明有环,这是片面的,因为我们可能一直重复该指令,比如下面的这种情况:
"GL"
输出:false
预期:true
讨论一下什么情况会回到起点;
- 第一:从
(0, 0) -> (x, x) -> ... -> (0, 0)
,这个很好想 - 第二:排除第一种情况后(注是排除),执行完一遍指令 instructions 后,只要方向与初始方向不同,那么执行 n 次指令机器人也不可能回到原点,因为它的运动范围只会不断地向外扩张
class Solution {
final static int U = 0, D = 1, L = 2, R = 3;
public boolean isRobotBounded(String instructions) {
char s[] = instructions.toCharArray();
int x = 0, y = 0, d = U;
for (char c : s) {
if (c == 'G') {
switch (d) {
case U: x--; break;
case D: x++; break;
case L: y--; break;
case R: y++; break;
}
} else if (c == 'L') {
switch (d) {
case U: d = L; break;
case D: d = R; break;
case L: d = D; break;
case R: d = U; break;
}
} else { // else if (c == 'R')
switch (d) {
case U: d = R; break;
case D: d = L; break;
case L: d = U; break;
case R: d = D; break;
}
}
}
return (x == 0 && y == 0) || d != U;
}
}
这个代码比较冗余,方向之间的转移可以通过数字变化来进行转移,比如 1>2, 2->3, 3->4, 4->1,而 4->1 可以通过取模来实现
注:方向数组内部的一维数组的顺序是根据你的取模逻辑取定义的,如果当前方向是向北(k = 0),那么遇到向左转,此时你的方向数组的 k+1 位置应该是向西 (0, -1)
class Solution {
final static int[][] dir = { {1,0},{0,-1},{-1,0},{0,1} }; //北、西、
public boolean isRobotBounded(String instructions) {
char s[] = instructions.toCharArray();
int x = 0, y = 0, k = 0;
for (char c : s) {
if (c == 'L') {
k = (k + 1) % 4;
} else if (c == 'R'){
k = (k + 3) % 4;
} else {
x += dir[k][0];
y += dir[k][1];
}
}
return (x == 0 && y == 0) || k != 0;
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,