《程序员面试金典(第6版)》面试题 16.22. 兰顿蚂蚁(哈希映射,C++)

news2024/12/25 1:06:37

题目描述

一只蚂蚁坐在由白色和黑色方格构成的无限网格上。开始时,网格全白,蚂蚁面向右侧。每行走一步,蚂蚁执行以下操作。传送门

  • (1) 如果在白色方格上,则翻转方格的颜色,向右(顺时针)转 90 度,并向前移动一个单位。
  • (2) 如果在黑色方格上,则翻转方格的颜色,向左(逆时针方向)转 90 度,并向前移动一个单位。

编写程序来模拟蚂蚁执行的前 K 个动作,并返回最终的网格。

  • 网格由数组表示,每个元素是一个字符串,代表网格中的一行,黑色方格由 ‘X’ 表示,白色方格由 ‘_’ 表示,蚂蚁所在的位置由 ‘L’, ‘U’, ‘R’, ‘D’ 表示,分别表示蚂蚁 左、上、右、下 的朝向。只需要返回能够包含蚂蚁走过的所有方格的最小矩形。

示例 1:

输入: 0
输出: ["R"]

示例 2:

输入: 2
输出:
[
  "_X",
  "LX"
]

示例 3:

输入: 5
输出:
[
  "_U",
  "X_",
  "XX"
]

说明:

  • K <= 100000

解题思路与代码

emmmmm,这道题,是一道相当困难的题。困难的点在于题目的理解方面。我感觉,阅读理解不是顶级的选手,做这道题可能都得吃瘪。

首先,这道题,可不是简简单单的这句话而已只需要返回能够包含蚂蚁走过的所有方格的最小矩形。
就看那个返回值,你可能就会迷糊住,为啥输入2,返回的确实那样的呢?蚂蚁明明只走了2步,为啥有4个格子?是不是就会感到很疑惑?

在看到,蚂蚁在白格黑格上面反复跳跃,还正着反着转圈圈,我估计你就觉得更恶心把,咋会有人出这样的题,还不好好写题目说明,对吧。

其他方面倒是还好,只要彻底理解了题意,这道题也不算是特别困难的题,但也是一道中等难度偏上的题。因为除了基本的映射外,颜色的反转,不同的方向转圈,确实得够你吃一壶的。

那八皇后这道题来对比,题目难理解程度更高,题目复杂程度差不多,但我感觉也更高一些。

这里我再补充一下解题的思路:

  • 初始化网格:首先,我们需要创建一个足够大的二维网格,用来模拟蚂蚁的移动。这个网格应该足够大,以至于在蚂蚁的前K步移动中,它不会走出网格。每个单元格的初始值为’_',表示白色方格。我们还需要将蚂蚁的初始位置和朝向设定好。

  • 模拟蚂蚁的移动:对于前K步,我们需要根据蚂蚁当前所在的单元格的颜色和蚂蚁的朝向来决定下一步的移动。如果蚂蚁在白色方格上,我们需要把方格颜色翻转为黑色,然后蚂蚁向右转90度并向前移动一个单位。反之,如果蚂蚁在黑色方格上,我们需要把方格颜色翻转为白色,然后蚂蚁向左转90度并向前移动一个单位。注意,我们需要更新蚂蚁的朝向。

  • 处理网格扩展:由于蚂蚁的移动可能会超出当前网格的边界,我们需要在这种情况下动态地扩展网格。当蚂蚁即将走出网格时,我们可以添加新的行或列来扩展网格。

  • 提取结果:最后,我们需要找到包含蚂蚁走过的所有单元格的最小矩形,并返回这个矩形。这个矩形可以通过找到蚂蚁走过的单元格的最小和最大的行号和列号来确定。在提取结果时,我们需要把蚂蚁所在的位置和朝向也包含进去。

方法一 : 哈希法

接下来我就讲一下这道题基本的做法:

  • 这道题我们要创建很多的变量,来标记一些东西。首先是,蚂蚁走过的格子,我们也可以把它映射到一个无限延伸的棋盘上。
  • 那么如何去创建这个棋盘呢?首先普通的二维数组不能满足,因为棋盘不光有x,y坐标,还有它拥有的一种额外的属性,那便是颜色。蚂蚁走过的格子可是会变色的啊。
  • 那么怎么办呢?我们要创建一个嵌套的unordered_map<int, unordered_map<int, bool>> map;来表示这个棋盘,其中外层的键是y坐标,内层的键是x坐标,内层的值呢,就是棋盘格子的颜色啦,完美符合要求。
  • 之后,创建一个蚂蚁朝向的数组,代表蚂蚁的方向。char dirs[] = {'R','D','L','U'}; 之后再创建一个当前蚂蚁朝向的对应数组的下标变量int dir = 0; // 0是向右,1是向下,2是向左,3是向上
  • 接着定义蚂蚁的初始坐标int x = 0, y = 0,再定义两个数组,结合着dir,为的是去确定蚂蚁走后一步x,y是什么。
    • int dx[] = {1,0,-1,0}, dy[] = {0,1,0,-1};
  • 最后创建4个边界变量,这些边界变量的作用就是圈出棋盘的矩形出来。等会在while循环的遍历中,我们要不断的去更新这些边界变量。
    • int maxX = 0, maxY = 0, minX = 0, minY = 0;
  • 之后呢,我们使用一个while循环,去把蚂蚁走过的格子,颜色,等等,都遍历到那个嵌套map中去。你可以先想一下如何遍历,我们代码里会具体交代的。
  • 这样,我们就得到了一个蚂蚁走过的所有格子的动态棋盘。这样,其实我们就可以正式的准备最后的返回结果了。
  • 创建一个vector<string> result (maxY - minY + 1,string(maxX - minX + 1,'_'));并将返回结果的部分棋盘全部初始化为白色。至于result结果集为什么这样去初始化,我就不用再细细讲了吧。
  • 最后用双层for循环,再次将嵌套map的动态棋盘映射到数组中,但是注意,前面的动态棋盘x,y的值有正有负。但是在数组中,x,y的值就必须都是正的。所以我们要平移整个蚂蚁走过的区域。这也就是为什么我们当初要创建边界变量的原因。
  • 最后的最后,在把蚂蚁的朝向映射到返回数组中,我们就可以提交结果了。

具体的代码如下:

class Solution {
public:
    vector<string> printKMoves(int K) {
        unordered_map<int, unordered_map<int, bool>> map; // 定义一个嵌套哈希map,来存储坐标以及坐标对应的颜色
        int dir = 0; // 0是向右,1是向下,2是向左,3是向上
        int x = 0, y = 0; // 定义蚂蚁的初始坐标。
        char dirs[] = {'R','D','L','U'}; // 用来最后确定蚂蚁朝向的数组
        // dx,dy是用来帮助记录蚂蚁走后的坐标与朝向的。
        int dx[] = {1,0,-1,0}, dy[] = {0,1,0,-1};
        // 记录最大的,最小的x,y的坐标值
        int maxX = 0, maxY = 0, minX = 0, minY = 0;
        while(K--){ // 把蚂蚁走过的所有格子,都遍历进这个map中,并标记颜色
            // 先根据格子颜色,决定朝哪个方向走
            if(map[y][x]) dir = (dir + 3) % 4; 
            else dir = (dir + 1) % 4;
            // 再反转当前格子颜色
            map[y][x] = !map[y][x];
            // 之后再走一步
            x += dx[dir];
            y += dy[dir];
            // 最后更新边界信息
            minX = min(minX,x);
            minY = min(minY,y);
            maxX = max(x,maxX);
            maxY = max(y,maxY);
        }
        // 创建一个最后的结果集,由于最后的数组的坐标都是正的,而map中记录的坐标有正有负,所以要根据最左下角坐标去做整体图形的平移 
        // 所有点位偏移(minx,miny) 个距离。
        vector<string> result (maxY - minY + 1,string(maxX - minX + 1,'_'));
        for(auto& i : map)
            for(auto& j : i.second)
                if(j.second)
                    result[i.first - minY][j.first - minX] = 'X';
        // 由于最后蚂蚁停留在在 (x,y)上,但是这个点有正负,要返回偏移后的点。
        result[y - minY][x - minX] = dirs[dir];
        return result;
    }
};

在这里插入图片描述

复杂度分析

时间复杂度:O(K)

  • 时间复杂度主要由蚂蚁移动的步数 K 决定,每次移动的操作包括更新蚂蚁的方向、坐标以及对应格子的颜色,这些操作的时间复杂度都是常数时间 O(1)。另外,在蚂蚁完成所有移动后,还需要遍历一次 map 来构造最终的结果,这个过程的时间复杂度取决于蚂蚁访问过的格子数量,但由于蚂蚁最多只能移动 K 步,所以访问过的格子数量不会超过 K,因此这个过程的时间复杂度也是 O(K)。综上,整个代码的时间复杂度是 O(K)。

空间复杂度:O(K)

  • 空间复杂度主要由 map 的大小决定,map 中存储了蚂蚁访问过的所有格子的坐标以及对应的颜色,每次移动都可能访问到一个新的格子,所以 map 的大小最多为 K,因此空间复杂度是 O(K)。另外,最终的结果 result 占用的空间也取决于蚂蚁访问过的格子数量,但同样不会超过 K,所以这部分的空间复杂度也是 O(K)。综上,整个代码的空间复杂度是 O(K)。

这里假设 K 是蚂蚁的移动步数,如果 K 代表其他的量(例如格子的数量、方向的数量等),那么复杂度可能会不同。

总结

这道题目是一道模拟题,其主要目的是考察编程能力、逻辑思考能力以及对细节的把握。题目中蚂蚁在格子上行走的规则,以及最后需要返回的结果都具有一定的复杂性。这要求你能够准确地理解题意,找出解题的规律,并且把规律用代码实现出来。

具体到这道题,它考察了以下几个方面的能力:

  • 对数据结构的运用:这道题中需要用到嵌套的哈希表来记录蚂蚁走过的每个格子的颜色。

  • 对模拟问题的处理:你需要根据题目的描述,模拟出蚂蚁在格子上行走的过程。

  • 对边界的处理:你需要找出蚂蚁走过的格子中x坐标和y坐标的最大值和最小值,以此来确定最后返回结果的大小。

  • 对细节的把握:题目中蚂蚁在白色格子和黑色格子上的行为是不同的,这是解题的关键,需要仔细理解并准确实现。

所以,这道题的意义主要是考察你的编程能力、逻辑思考能力以及对细节的把握。

最后的最后,如果你觉得我的这篇文章写的不错的话,请给我一个赞与收藏,关注我,我会继续给大家带来更多更优质的干货内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/526988.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Vue2.0源码学习】虚拟DOM篇-Vue中的虚拟DOM

文章目录 1. 前言2. 虚拟DOM简介3. Vue中的虚拟DOM3.1 VNode类3.2 VNode的类型3.2.1 注释节点3.2.2 文本节点3.2.3 克隆节点3.2.4 元素节点3.2.5 组件节点3.2.6 函数式组件节点3.2.7 小结 3.3 VNode的作用 4. 总结 1. 前言 虚拟DOM&#xff0c;这个名词作为当下的前端开发人员…

Android Studio Flamingo (火烈鸟) 升级踩坑记录

由于想要验证Compose最新的debug特性&#xff0c;而我目前使用的版本&#xff08;Dolphin 小海豚&#xff09;不支持&#xff0c;查看官网说明需要最新版本&#xff0c;所以不得已进行了一下Android Studio版本升级&#xff0c;过程中遇到一些问题&#xff0c;本文仅做记录。&a…

FPGA驱动WM8731音频收发全网最细讲解 提供2套工程源码和技术支持

目录 1、前言2、WM8731音频解读3、vivado工程1介绍4、vivado工程2介绍5、上板调试验证6、资料获取 1、前言 本文用FPGA驱动WM8731音频芯片&#xff0c;实现音频相关的应用&#xff0c;适用于在校学生做毕业设计、研究生项目开发&#xff0c;也适用于在职工程师做项目开发&…

Ae 首选项:启动和修复

使用“首选项”里面的启动和修复 Start and Repair面板&#xff0c;可以解决 Ae 中的首选项设置问题&#xff0c;而无需更改、删除或者重新进行设置。 启动选项 Startup Options 启用主屏幕 Enable Home Screen 确定是否在启动 Ae 时显示主屏幕。 更改将在下次启动时有效。 显示…

element-plus 问题

对话框内部下拉框会在左上角 在对话框内打开下拉框后点击关闭按钮&#xff0c;尚未关闭的下拉框会在左上角出现&#xff08;或闪现&#xff09; 解决方案&#xff1a; popper-append-to-body 此方法失效&#xff0c;改用 :teleported"false" teleported&#xff1a;…

JDBC和数据库连接池

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。 文章目录 JDBC 概述基本介绍模拟JDBCJDBC 带来的好处 JDBC 快速入门JDBC 程序编写步骤JDBC 第一个程序 获取数据库连接5种方式方式1…

接入 GPT-4 的 AI 虚拟女友,一周狂挣 50 万!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 随着 ChatGPT 的爆火&#xff0c;互联网上也衍生出不少令人直呼脑洞大开的 AI 应用。 最近&#xff0c;国外一位名为 Caryn Marjorie 的小姐姐搞了个骚操作&#xff0c;基于 GPT-4 调教出来…

Spring Cloud LoadBalancer是什么?

什么是Spring Cloud LoadBalancer Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器, 用来替代 Ribbon。 Spring官方提供了两种负载均衡的客户端&#xff1a; RestTemplate RestTemplate是Spring提供的用于访问Rest服务的客户端&#xff0c;RestTempla…

30从零开始学Java之详解面向对象的7种创建方式

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在上一篇文章中&#xff0c;壹哥给大家介绍了Java中的类及其特点、创建过程等内容&#xff0c;相信你…

【Nginx高级篇】Lua基础语法和OpenResty的安装

目录 一、前言 二、Lua基础语法 hello world 保留关键字 注释 变量 字符串 空值 布尔类型 作用域 控制语句 if-else for循环 函数 赋值 返回值 Table 数组 遍历 成员函数 三、openresty的安装 &#xff08;一&#xff09;预编译安装 &#xff08;二&…

VMware中Ubuntu拓展磁盘容量的两种方式 图形化方式命令行磁盘分区方式(亲测有效简单且详细)linux磁盘分区

文章目录 前言1. 软件设置扩容2. 容量查看3. 容量拓展实现3.1 图形化容量拓展分配3.2 磁盘命令行方式拓展容量3.2.1 确定磁盘挂载目录3.2.2 系统磁盘扩容 4. 分盘扩容TIPS&#xff1a;总结&#xff1a; 前言 在用VMware虚拟机的情况下&#xff0c;一开始分配的容量在使用过程中…

PMP项目管理-[第十二章]采购管理

采购管理知识体系&#xff1a; 规划采购管理&#xff1a; 实施采购&#xff1a; 控制采购&#xff1a; 12.1 规划采购管理 定义&#xff1a;记录项目采购决策、明确采购方法、识别潜在卖方的过程 作用&#xff1a;确定是否从项目外部获取货物或服务.如果是&#xff0c;则还要确…

循环结构程序设计

一、循环结构语句 C语言提供了三种循环语句&#xff08;for语句&#xff09;、while语句和do-while语句。 for语句&#xff1a; for(表达式1 &#xff1b; 表达式2 &#xff1b; 表达式3) {   循环体语句&#xff1b; } for语句的执行过程&#xff1a; 首先计算表达式1。判断…

【LED子系统】五、核心层详解(二)

个人主页&#xff1a;董哥聊技术 我是董哥&#xff0c;高级嵌入式软件开发工程师&#xff0c;从事嵌入式Linux驱动开发和系统开发&#xff0c;曾就职于世界500强公司&#xff01; 创作理念&#xff1a;专注分享高质量嵌入式文章&#xff0c;让大家读有所得&#xff01; 文章目录…

基于B/S架构、可替代付费商业软件的一站式量化交易平台

产品简介 这是一个面向程序员的量化交易软件&#xff0c;用于期货、股票、外汇、炒币等多种交易场景&#xff0c;实现自动交易。已对接了CTP接口&#xff08;国内期货&#xff09;、老虎证券接口&#xff08;美股港股&#xff09;。 功能特性&#xff1a; 一站式平台&#x…

Protell99SE祭文

Protell99SE祭文 大概是在21年前的今天&#xff0c;我和你结合在一起&#xff0c;陪伴走过无数的设计。 我的感觉&#xff0c;大概是在2021年吧&#xff0c;你逐渐离我远去。啊&#xff0c;Protel99SE时代一去不复返了。 我用了你21年&#xff0c;虽着AD软件的到来&#xff…

【C++】19.C++11

1.C11 auto 范围for 新容器 线程库列表初始化右值引用和移动语义 lambda表达式容器支持花括号列表初始化 本质是增加一个initializer_list的构造函数initializer_list支持花括号 2.列表初始化 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <ve…

​数字化转型升级之工业元宇宙与AIGC

月説小飞象交流会 生活就是&#xff0c;面对复杂&#xff0c;保持欢喜。心烦时&#xff0c;记住三句话&#xff1a;1、算了吧。2、没关系。3、会过去的。 内部交流│24期 数字化转型升级 工业元宇宙与AIGC data analysis ●●●● 分享人&#xff1a;李铁军 ‍ 现如今数字化不再…

定风波、渡重山、至未来:2023中国数字能源生态大会开启的新旅程

全球碳中和的时代背景下&#xff0c;面向3060发展目标&#xff0c;新使命、新技术、新应用的到来&#xff0c;都给能源产业带来了持续变革的必要性与可能性。 2023年5月11日&#xff0c;在2023中国数字能源生态大会上&#xff0c;华为数字能源技术有限公司总裁侯金龙发表了“融…

【微电网】含风、光、储联合发电的微电网优化调度研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…