Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
机器人在一个无限大小的 XY 网格平面上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令 commands :
-2 :向左转 90 度 -1 :向右转 90 度 1 <= x <= 9 :向前移动 x 个单位长度 在网格上有一些格子被视为障碍物 obstacles 。第 i 个障碍物位于网格点 obstacles[i] = (xi, yi) 。
机器人无法走到障碍物上,它将会停留在障碍物的前一个网格方块上,但仍然可以继续尝试进行该路线的其余部分。
返回从原点到机器人所有经过的路径点(坐标为整数)的最大欧式距离的平方。(即,如果距离为 5 ,则返回 25 )
注意:
- 北表示
+Y方向。 - 东表示
+X方向。 - 南表示
-Y方向。 - 西表示
-X方向。
示例
示例 1:
输入:commands = [4,-1,3], obstacles = []
输出:25
解释:
机器人开始位于 (0, 0):
1. 向北移动 4 个单位,到达 (0, 4)
2. 右转
3. 向东移动 3 个单位,到达 (3, 4)
距离原点最远的是 (3, 4) ,距离为 32 + 42 = 25
示例 2:
输入:commands = [4,-1,4,-2,4], obstacles = [[2,4]]
输出:65
解释:机器人开始位于 (0, 0):
1. 向北移动 4 个单位,到达 (0, 4)
2. 右转
3. 向东移动 1 个单位,然后被位于 (2, 4) 的障碍物阻挡,机器人停在 (1, 4)
4. 左转
5. 向北走 4 个单位,到达 (1, 8)
距离原点最远的是 (1, 8) ,距离为 12 + 82 = 65
提示:
- 1 <= commands.length <= 104
- commands[i] is one of the values in the list [-2,-1,1,2,3,4,5,6,7,8,9].
- 0 <= obstacles.length <= 104
- -3 * 104 <= xi, yi <= 3 * 104
- 答案保证小于 231
二、题解:
方法一 逐步比较法
- 原理。记录方向,执行x或者y更改,根据障碍数组修正x或y,记录当前最远点。
- 思路。
- 记录方向(0,1,2,3对应北东南西),
- 根据方向执行x或者y的更改
- 根据变动和变动之前的值,判断阻碍里是否有这个在中间的值,再进行重新赋值
- 使用Math.max比较当前最远点 Math.pow(x,2)+Math.pow(y,2)和之前的最远点
代码:
var robotSim = function(commands, obstacles) {
let x = 0;
let beforeX = 0
let y = 0;
let beforeY = 0
let max = 0
// let _arr = ['n','e','s','w']// 'n'北 'e'东 's'南 'w'西
let defalut = 0
for(let i=0;i<commands.length;i++){
if(commands[i] === -1){
defalut = (defalut+1+4)%4
continue
} else if(commands[i] === -2){
defalut = (defalut-1+4)%4
continue
}
if(defalut === 0){
y+=commands[i]
} else if(defalut === 1){
x+=commands[i]
}else if(defalut === 2){
y-=commands[i]
}else if(defalut === 3){
x-=commands[i]
}
for(let j=0;j<obstacles.length;j++){
if(obstacles[j][0] === x && defalut=== 0 && obstacles[j][1]>beforeY){
y = y>obstacles[j][1]-1?obstacles[j][1]-1:y
continue
}
if(obstacles[j][0] === x && defalut=== 2 && obstacles[j][1]<beforeY){
y = y<obstacles[j][1]+1?obstacles[j][1]+1:y
continue
}
if(obstacles[j][1] === y && defalut=== 1 && obstacles[j][0]>beforeX){
x = x>obstacles[j][0]-1?obstacles[j][0]-1:x
continue
}
if(obstacles[j][1] === y && defalut=== 3 && obstacles[j][0]<beforeX){
x = x<obstacles[j][0]+1?obstacles[j][0]+1:x
continue
}
}
beforeX = x
beforeY = y
max = Math.max(max, Math.pow(x,2)+Math.pow(y,2))
}
return max
};
- 优化思路。改一下判断。
代码:
var robotSim = function(commands, obstacles) {
let x = 0;
let beforeX = 0
let y = 0;
let beforeY = 0
let max = 0
let defalut = 0
for(let i=0;i<commands.length;i++){
let item = commands[i]
if(item === -1 || item === -2){
defalut = (defalut+1*(item===-2?-1:1)+4)%4
continue
}
if(defalut === 0 || defalut === 2){
y+=item*(defalut===2?-1:1)
} else if(defalut === 1 || defalut === 3){
x+=item*(defalut===3?-1:1)
}
for(let j=0;j<obstacles.length;j++){
let ob = obstacles[j]
if(ob[0] === x) {
if(defalut=== 0 && ob[1]>beforeY){
y = y>ob[1]-1?ob[1]-1:y
continue
}
if(defalut=== 2 && ob[1]<beforeY){
y = y<ob[1]+1?ob[1]+1:y
continue
}
}
if(ob[1] === y) {
if(defalut=== 1 && ob[0]>beforeX){
x = x>ob[0]-1?ob[0]-1:x
continue
}
if(defalut=== 3 && ob[0]<beforeX){
x = x<ob[0]+1?ob[0]+1:x
continue
}
}
}
beforeX = x
beforeY = y
max = Math.max(max, x*x+y*y)
}
return max
};
方法二 记录缺陷法
- 原理。逐步进行移动,记录缺陷的位置,使用set来提取是否到障碍。
代码:
var robotSim = function(commands, obstacles) {
let x = 0;
let y = 0;
const dirX = [0,1,0,-1]
const dirY = [1,0,-1,0]
let max = 0
let dirIndex = 0
const obArr = new Set()
for(let item of obstacles){
obArr.add(item[0]+'-'+item[1])
}
for(let item of commands){
if(item === -1 || item === -2){
dirIndex = (dirIndex+1*(item===-2?-1:1)+4)%4
}else {
for(let i=0;i<item;i++){
const tempX = x+dirX[dirIndex]
const tempY = y+dirY[dirIndex]
if(obArr.has(tempX+'-'+tempY)){
break
}
x = tempX
y = tempY
max = Math.max(max, x*x + y*y)
}
}
}
return max
};
方案比较
方案一 时间复杂度O(NK) 方案二 时间复杂度O(N+K)
三、总结
- 此题可以逐步比较法和记录缺陷法两种方案
- 逐步比较法主要是记录方向,执行x或者y更改,根据障碍数组修正x或y,记录当前最远点。
- 记录缺陷法逐步进行移动,记录缺陷的位置,使用set来提取是否到障碍。
文中如有错误,欢迎在评论区指正