int[][] dirs = new int[][]{{0,1}, {-1,0}, {0,-1}, {1,0}};
来表示向 北 西 南 东
走一步int x = 0, y = 0, d = 0
xy 表示坐标,d表示方向,要和上面表示的方向对应d = 0 表示北
d = 1 表示西
d = 2 表示南
d = 3 表示东
即逆时针一圈d = (d+1) % 4
右转:d = ((d - 1) % 4 + 4) % 4 => d = (d + 3) % 4
经过多次指令 instructions
后,判断机器人是不是能回到原点。
解析:
(0, 0)
不看方向class Solution {
public boolean isRobotBounded(String instructions) {
int x = 0, y = 0, d = 0; // d用来控制方向,d为0表示向北
int[][] dirs = new int[][]{{0,1}, {-1,0}, {0,-1}, {1,0}};
for(char c : instructions.toCharArray()){
if(c == 'G'){
x += dirs[d][0];
y += dirs[d][1];
}else if(c == 'L'){
d = (d + 1) % 4; // 每次左转,d就能加1
}else if(c == 'R'){
d = ((d - 1) % 4 + 4) % 4; // 每次右转,d-1,但是为了让d在 0 - 4里面,就需要+4
// d = (d + 3) % 4;
}
}
return (x==0&&y==0) || d != 0;
}
}
经过多次指令 commands
后,机器人离原点的最大欧式距离的平方,注意存在障碍物 obstacles
,有障碍物不能越过,只能停在前一个位置,但不影响后续指令
解析:
class Solution {
public int robotSim(int[] commands, int[][] obstacles) {
// 存障碍物,直接将 x y 存为String形式
Set<String> set = new HashSet<>();
for(int[] o : obstacles) set.add(o[0] + "," + o[1]);
// 方向 南 北 西 东 ==> 要与d对应 0表示向北走一步 1西走 2南走 3东走
int[][] dirs = new int[][]{{0, 1}, {-1, 0}, {0, -1}, {1, 0}};
int ans = 0;
// x代表东西走,y代表南北走 d代表方向 0北 1西 2南 3东
int x = 0, y = 0, d = 0;
for(int i = 0; i < commands.length; i++){
if(commands[i] == -2){
// 左转 顺时针转,方向都会 + 1
// d = d == 3 ? 0 : d + 1;
d = (d + 1) % 4; // 左转相当于方向+1
}else if(commands[i] == -1){
// 右转 逆时针转,方向都会 - 1
// d = d == 0 ? 3 : d - 1;
d = (d + 3) % 4; // 右转相当于左转3次
}else{
// 没有遇到障碍物会一直走,直到这一轮的步数走完
// 有障碍物就不会再走一步
while(commands[i] > 0 && !set.contains((x + dirs[d][0]) + "," + (y + dirs[d][1]))){
x += dirs[d][0];
y += dirs[d][1];
commands[i]--;
}
ans = Math.max(ans, x*x + y*y);
}
}
return ans;
}
}
在一个网格内行走,走到了边界就逆时针旋转90°,然后继续向前走,设置行走的方法函数。
解析:
(0, 0)
的朝向问题,因为可能刚好走回来到这个点,就超南,如果没有移动过就超东class Robot {
// 前进的四个方向
String[] ss = new String[]{"East", "North", "West", "South"};
int w, h, loc; // loc :有效(取模后)移动步数
boolean moved; // 记录是否经过移动,用于判断 (0, 0) 的方向
public Robot(int width, int height) {
w = width;
h = height;
}
public void step(int num) {
moved = true;
loc += num; // 只用知道总步数就行了,因为他一直在转圈圈
loc = loc % (2 * (w - 1) + 2 * (h - 1)); // 路程超过了一圈,直接取模,看位置在哪里就行了,不用真的走
}
public int[] getPos() {
int[] info = move();
return new int[]{info[0], info[1]};
}
public String getDir() {
int[] info = move();
// x y 代表方向, dir 代表朝向
int x = info[0], y = info[1], dir = info[2];
// (0, 0) 时, 当未移动过方向为 East, 移动过方向为 South (从上指过来)
if(x == 0 && y == 0) return moved ? ss[3] : ss[0];
return ss[dir];
}
int[] move(){
if(loc <= w - 1){
// 当移动的步数在[0, w - 1] 时,所在位置在外圈下方,方向为East
return new int[]{loc, 0, 0};
}else if(loc <= (w - 1) + (h - 1)){
// 往右走到底,然后往上走,方向为:North
return new int[]{w-1, loc - (w - 1), 1};
}else if(loc <= 2 * (w - 1) + (h - 1)){
// 往右走到底,然后往上走到底,又往左走,方向:West
return new int[]{(w - 1) - (loc - ((w - 1) + (h - 1))), h - 1, 2};
}else {
// 最后一种情况是在左边做外圈,往下走
return new int[]{0, (h - 1) - (loc - (2 * (w - 1) + (h - 1))), 3};
}
}
}