【前端也得会算法】874. 模拟行走机器人 [ 中等 ]

356 阅读2分钟

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
};

image.png

  • 优化思路。改一下判断。

代码:

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
};

image.png

方法二 记录缺陷法

  • 原理。逐步进行移动,记录缺陷的位置,使用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
};

image.png

方案比较

方案一 时间复杂度O(NK) 方案二 时间复杂度O(N+K)

三、总结

  • 此题可以逐步比较法记录缺陷法两种方案
  • 逐步比较法主要是记录方向,执行x或者y更改,根据障碍数组修正x或y,记录当前最远点。
  • 记录缺陷法逐步进行移动,记录缺陷的位置,使用set来提取是否到障碍。

文中如有错误,欢迎在评论区指正