一.题目
在无限的平面上,机器人最初位于 (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'
二.解析
思路是和官方一样的,结论就是第一轮结束时,如果在原地或者方向不是北,那么平面就存在环,机器人无法离开,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]))
};
当然两种写法的思路是一样的,写法二会更加优雅一些。
以上