LeetCode 每日一题笔记 日期:2025.04.06 题目:874. 模拟行走机器人

LeetCode 每日一题笔记

0. 前言

  • 日期:2025.04.06
  • 题目:874. 模拟行走机器人
  • 难度:中等
  • 标签:数组 哈希表 模拟

1. 题目理解

问题描述

机器人在一个无限大小的 XY 网格平面上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令 commands :

-2 :向左转 90 度

-1 :向右转 90 度

1 <= x <= 9 :向前移动 x 个单位长度

在网格上有一些格子被视为障碍物 obstacles 。第 i 个障碍物位于网格点 obstaclesi = (xi, yi)。

机器人无法走到障碍物上,它将会停留在障碍物的前一个网格方块上,并继续执行下一个命令。

返回机器人距离原点的 最大欧式距离 的 平方 。

注意:

北方表示 +Y 方向。

东方表示 +X 方向。

南方表示 -Y 方向。

西方表示 -X 方向。

原点 0,0 可能会有障碍物。

示例

输入:commands = 4,-1,3, obstacles = \[\]

输出:25

解释:

机器人开始位于 (0, 0):

  1. 向北移动 4 个单位,到达 (0, 4)
  2. 右转
  3. 向东移动 3 个单位,到达 (3, 4)
    距离原点最远的是 (3, 4) ,距离为 3² + 4² = 25

2. 解题思路

核心观察

  • 机器人仅有北、东、南、西四个朝向,左转/右转会让朝向循环切换;
  • 移动时必须逐格检查障碍物,遇到障碍物立即停止当前移动指令;
  • 使用哈希集合存储障碍物坐标,可实现O(1)时间复杂度的障碍物查询;
  • 只需记录过程中的最大距离平方,无需计算实际欧式距离。

算法步骤

  1. 障碍物预处理:将所有障碍物坐标存入哈希集合,方便快速判断;
  2. 初始化参数:起始坐标(0,0)、初始朝向北方、最大距离平方为0;
  3. 遍历执行命令
    • 转向命令:调整机器人的朝向状态;
    • 移动命令:按照当前朝向逐格移动,每一步校验是否存在障碍物,无障碍物则更新坐标,同步更新最大距离平方;
  4. 返回结果:遍历完所有命令后,输出最大距离平方。

3. 代码实现

java 复制代码
package com.sheeta1998.lec.lc874;

import java.util.HashSet;
import java.util.Set;

class Solution {

    public void setAdd(Set<String> set, int a, int b) {
        String ad = a + "," + b;
        set.add(ad);
    }

    public boolean setCompare(Set<String> set, int a, int b) {
        String cp = a + "," + b;
        return !set.contains(cp);
    }


    public int robotSim(int[] commands, int[][] obstacles) {
        int res = 0;
        int sta = 1;// 1 北,2东,3南,4西
        int x = 0;
        int y = 0;
        Set<String> set = new HashSet<>();
        for (int i = 0; i < obstacles.length; i++) {
            setAdd(set, obstacles[i][0], obstacles[i][1]);
        }
        for (int i = 0; i < commands.length; i++) {

            int a = commands[i];
            if (a < 0) {
                if (a == -1) {
                    if (sta != 4) {
                        sta += 1;
                    } else {
                        sta = 1;
                    }
                } else {
                    if (sta != 1) {
                        sta -= 1;
                    } else {
                        sta = 4;
                    }
                }
            } else {
                if (sta == 1) {
                    for (int j = 0; j < a; j++) {
                        if (!setCompare(set, x, y + 1)) {
                            break;
                        } else {
                            y++;
                        }

                    }
                    res= Math.max(res,x*x+y*y);
                } else if (sta == 2) {
                    for (int j = 0; j < a; j++) {
                        if (!setCompare(set, x + 1, y)) {
                            break;
                        } else {
                            x++;
                        }

                    }
                    res= Math.max(res,x*x+y*y);
                } else if (sta == 3) {
                    for (int j = 0; j < a; j++) {
                        if (!setCompare(set, x, y - 1)) {
                            break;
                        } else {
                            y--;
                        }

                    }
                    res= Math.max(res,x*x+y*y);
                } else {
                    for (int j = 0; j < a; j++) {
                        if (!setCompare(set, x - 1, y)) {
                            break;
                        } else {
                            x--;
                        }

                    }
                   res= Math.max(res,x*x+y*y);
                }
            }

        }

        return res;
    }
}

4. 代码优化说明

优化点1:方向简化

使用二维数组存储四个方向的坐标增量,替代数字状态判断,大幅简化代码逻辑:

java 复制代码
int[][] dirs = {{0,1},{1,0},{0,-1},{-1,0}}; // 北、东、南、西
int d = 0; // 方向索引

优化点2:障碍物存储优化

使用Long类型替代字符串存储坐标,减少字符串拼接开销,查询效率更高:

java 复制代码
Set<Long> set = new HashSet<>();
long code = ((long)x << 32) | (y & 0xFFFFFFFFL);

优化点3:精简重复逻辑

合并最大距离更新的代码,消除冗余逻辑。

5. 复杂度分析

  • 时间复杂度 :O(M+N×K)O(M + N \times K)O(M+N×K)

    • MMM 为障碍物数量,预处理障碍物耗时 O(M)O(M)O(M);
    • NNN 为命令数量,KKK 为单次移动的最大步数(9),移动操作总耗时 O(N×K)O(N \times K)O(N×K);
    • 障碍物查询为 O(1)O(1)O(1) 操作。
  • 空间复杂度 :O(M)O(M)O(M)

    • 哈希集合存储障碍物坐标,空间大小与障碍物数量成正比。

6. 总结

  • 核心思路是模拟机器人行走 + 哈希表快速查障,严格按照题目规则逐命令执行、逐格移动校验;
  • 关键技巧:通过状态标记管理机器人朝向,利用哈希集合解决障碍物查询的效率问题;
  • 本题重点考察模拟能力和哈希表的实际应用,无需复杂算法,重点在于逻辑严谨性。

关键点回顾

  1. 机器人四个朝向循环切换,转向逻辑需处理边界(如北左转→西);
  2. 移动必须逐格判断,遇到障碍物立即终止当前移动指令;
  3. 哈希表是解决障碍物快速查询的最优方案。
相关推荐
RainCity5 天前
Java Swing 自定义组件库分享(十二)
java·笔记·后端
To_OC5 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC5 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
To_OC6 天前
LC 994 腐烂的橘子:人人都说是 BFS 入门题,我却写了三遍才过
javascript·算法·leetcode
To_OC6 天前
LC 200 岛屿数量:经典 DFS 入门题,我第一次写居然连方向都搞错了
javascript·算法·leetcode
To_OC7 天前
LC 128 最长连续序列:别上来就排序,O (n) 解法才是这题的灵魂
javascript·算法·leetcode
To_OC9 天前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
To_OC10 天前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
LinXunFeng12 天前
Obsidian - 使用 Share Note 分享笔记并自部署
前端·笔记·github