哈希表题目:猜数字游戏
文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法一
- 思路和算法
- 代码
- 复杂度分析
- 解法二
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题:猜数字游戏
出处:299. 猜数字游戏
难度
4 级
题目描述
要求
你在和朋友一起玩猜数字(Bulls and Cows)游戏。
你写出一个秘密数字,并请朋友猜这个数字是多少。朋友每猜测一次,你就会给他一个包含下述信息的提示:
- 「公牛」的数量,即猜测数字中有多少位数字在秘密数字中出现且位置正确。
- 「奶牛」的数量,即猜测数字中有多少位数字在秘密数字中出现但位置错误,即猜测数字中有多少位非公牛数字可以通过重新排列变成公牛数字。
给你一个秘密数字 secret\texttt{secret}secret 和朋友猜测的数字 guess\texttt{guess}guess,请你返回对朋友这次猜测的提示。
提示的格式为 "xAyB"\texttt{"xAyB"}"xAyB",x\texttt{x}x 是公牛个数,y\texttt{y}y 是奶牛个数。请注意 secret\texttt{secret}secret 和 guess\texttt{guess}guess 都可能含有重复数字。
示例
示例 1:
输入:secret="1807",guess="7810"\texttt{secret = "1807", guess = "7810"}secret = "1807", guess = "7810"
输出:"1A3B"\texttt{"1A3B"}"1A3B"
解释:数字和位置都对(公牛)用 ‘|’\texttt{`|'}‘|’ 连接,数字猜对位置不对(奶牛)用下划线表示。
"1807"\texttt{"1807"}"1807"
|\texttt{~~|} |
"7‾810‾"\texttt{"}\underline{\texttt{7}}\texttt{8}\underline{\texttt{10}}\texttt{"}"7810"
示例 2:
输入:secret="1123",guess="0111"\texttt{secret = "1123", guess = "0111"}secret = "1123", guess = "0111"
输出:"1A1B"\texttt{"1A1B"}"1A1B"
解释:数字和位置都对(公牛)用 ‘|’\texttt{`|'}‘|’ 连接,数字猜对位置不对(奶牛)用下划线表示。
"1123"\texttt{"1123"}"1123"
|\texttt{~~|} |
"011‾1"\texttt{"01}\underline{\texttt{1}}\texttt{1"}"0111"
或
"1123"\texttt{"1123"}"1123"
|\texttt{~~|} |
"0111‾"\texttt{"011}\underline{\texttt{1}}\texttt{"}"0111"
注意,两个不匹配的 1\texttt{1}1 中,只有一个会算作奶牛(数字猜对位置不对),因为通过重新排列非公牛数字之后只有一个 1\texttt{1}1 可以成为公牛数字。
示例 3:
输入:secret="1",guess="0"\texttt{secret = "1", guess = "0"}secret = "1", guess = "0"
输出:"0A0B"\texttt{"0A0B"}"0A0B"
示例 4:
输入:secret="1",guess="1"\texttt{secret = "1", guess = "1"}secret = "1", guess = "1"
输出:"1A0B"\texttt{"1A0B"}"1A0B"
数据范围
- 1≤secret.length,guess.length≤1000\texttt{1} \le \texttt{secret.length, guess.length} \le \texttt{1000}1≤secret.length, guess.length≤1000
- secret.length=guess.length\texttt{secret.length = guess.length}secret.length = guess.length
- secret\texttt{secret}secret 和 guess\texttt{guess}guess 仅由数字组成
解法一
思路和算法
公牛为 secret\textit{secret}secret 和 guess\textit{guess}guess 的相同下标处数字相同的下标个数,统计公牛的方法是:同时遍历 secret\textit{secret}secret 和 guess\textit{guess}guess,对于每个下标,如果 secret\textit{secret}secret 和 guess\textit{guess}guess 在相同下标处的数字相同,则将公牛的数量加 111。
奶牛为 secret\textit{secret}secret 和 guess\textit{guess}guess 的不同下标处数字相同的下标个数,统计奶牛的方法是:使用两个哈希表分别记录 secret\textit{secret}secret 和 guess\textit{guess}guess 中的每个数字的出现次数(排除公牛的情况),同时遍历 secret\textit{secret}secret 和 guess\textit{guess}guess,对于每个下标,如果 secret\textit{secret}secret 和 guess\textit{guess}guess 在相同下标处的数字不同,则将该下标处的两个数字在对应的哈希表中的出现次数分别加 111,遍历结束之后,000 到 999 的每个数字在奶牛中的数量为该数字在两个哈希表中的出现次数的较小值,计算每个数字在奶牛中的数量之和,即为奶牛的数量。
由于统计公牛和奶牛都需要同时遍历 secret\textit{secret}secret 和 guess\textit{guess}guess,因此可以在一次遍历中完成统计公牛和奶牛的操作。遍历过程中,如果 secret\textit{secret}secret 和 guess\textit{guess}guess 在相同下标处的数字相同则将公牛的数量加 111,如果 secret\textit{secret}secret 和 guess\textit{guess}guess 在相同下标处的数字不同则将该下标处的两个数字在 secret\textit{secret}secret 和 guess\textit{guess}guess 中的出现次数分别加 111,遍历结束之后遍历 000 到 999 在 secret\textit{secret}secret 和 guess\textit{guess}guess 中的出现次数,统计奶牛的数量。
实现方面,由于数字范围是 000 到 999,因此可以使用两个数组分别记录 secret\textit{secret}secret 和 guess\textit{guess}guess 中的每个数字的出现次数。
代码
class Solution {public String getHint(String secret, String guess) {int bulls = 0, cows = 0;int[] secretCounts = new int[10];int[] guessCounts = new int[10];int length = secret.length();for (int i = 0; i < length; i++) {int secretDigit = secret.charAt(i) - '0';int guessDigit = guess.charAt(i) - '0';if (secretDigit == guessDigit) {bulls++;} else {secretCounts[secretDigit]++;guessCounts[guessDigit]++;}}for (int i = 0; i < 10; i++) {cows += Math.min(secretCounts[i], guessCounts[i]);}return String.format("%dA%dB", bulls, cows);}
}
复杂度分析
-
时间复杂度:O(n+C)O(n + C)O(n+C),其中 nnn 是字符串 secret\textit{secret}secret 和 guess\textit{guess}guess 的长度,CCC 是数字的个数,C=10C = 10C=10。需要 O(n)O(n)O(n) 的时间遍历字符串 secret\textit{secret}secret 和 guess\textit{guess}guess 各一次统计公牛数量和每个数字的出现次数,需要 O(C)O(C)O(C) 的时间遍历 000 到 999 的所有数字统计奶牛数量。
-
空间复杂度:O(C)O(C)O(C),其中 CCC 是数字的个数,C=10C = 10C=10。需要使用两个哈希表分别记录 secret\textit{secret}secret 和 guess\textit{guess}guess 中的每个数字的出现次数。
解法二
思路和算法
解法一需要使用两个哈希表分别记录 secret\textit{secret}secret 和 guess\textit{guess}guess 中的每个数字的出现次数,在遍历 secret\textit{secret}secret 和 guess\textit{guess}guess 之后还需要遍历 000 到 999 的每个数字计算奶牛的数量。可以只用一个哈希表,在遍历 secret\textit{secret}secret 和 guess\textit{guess}guess 的同时计算奶牛的数量。
使用一个哈希表记录每个数字的出现次数(排除公牛的情况),遍历 secret\textit{secret}secret 和 guess\textit{guess}guess 的过程中,对于 secret\textit{secret}secret 中出现的每个数字将出现次数加 111,对于 guess\textit{guess}guess 中出现的每个数字将出现次数减 111。上述操作的思想是:对于 secret\textit{secret}secret 中的每个数字,只有当 guess\textit{guess}guess 中存在一个不同位置的相同数字时,才是一个奶牛,反之亦然。
当遍历到一个下标时,将 secret\textit{secret}secret 和 guess\textit{guess}guess 在该下标处的数字分别记为 secretDigit\textit{secretDigit}secretDigit 和 guessDigit\textit{guessDigit}guessDigit,如果 secretDigit=guessDigit\textit{secretDigit} = \textit{guessDigit}secretDigit=guessDigit 则将公牛的数量加 111,如果 secretDigit≠guessDigit\textit{secretDigit} \ne \textit{guessDigit}secretDigit=guessDigit 则按照如下操作统计奶牛:
-
如果哈希表中 secretDigit\textit{secretDigit}secretDigit 的出现次数小于 000,则在之前遍历的 guess\textit{guess}guess 的数字中有多余的 secretDigit\textit{secretDigit}secretDigit,因此将奶牛的数量加 111;
-
如果哈希表中 guessDigit\textit{guessDigit}guessDigit 的出现次数大于 000,则在之前遍历的 secret\textit{secret}secret 的数字中有多余的 guessDigit\textit{guessDigit}guessDigit,因此将奶牛的数量加 111;
-
将 secretDigit\textit{secretDigit}secretDigit 在哈希表中的出现次数加 111,将 guessDigit\textit{guessDigit}guessDigit 在哈希表中的出现次数减 111。
遍历结束之后,即可知道奶牛的数量。
代码
class Solution {public String getHint(String secret, String guess) {int bulls = 0, cows = 0;int[] digits = new int[10];int length = secret.length();for (int i = 0; i < length; i++) {int secretDigit = secret.charAt(i) - '0';int guessDigit = guess.charAt(i) - '0';if (secretDigit == guessDigit) {bulls++;} else {if (digits[secretDigit] < 0) {cows++;}if (digits[guessDigit] > 0) {cows++;}digits[secretDigit]++;digits[guessDigit]--;}}return String.format("%dA%dB", bulls, cows);}
}
复杂度分析
-
时间复杂度:O(n)O(n)O(n),其中 nnn 是字符串 secret\textit{secret}secret 和 guess\textit{guess}guess 的长度。需要遍历字符串 secret\textit{secret}secret 和 guess\textit{guess}guess 各一次统计公牛数量和奶牛数量。
-
空间复杂度:O(C)O(C)O(C),其中 CCC 是数字的个数,C=10C = 10C=10。需要使用一个哈希表记录每个数字的出现次数。
相关文章:
哈希表题目:猜数字游戏
文章目录题目标题和出处难度题目描述要求示例数据范围解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析题目 标题和出处 标题:猜数字游戏 出处:299. 猜数字游戏 难度 4 级 题目描述 要求 你在和朋友一起玩猜数字(Bulls…...

项目请求地址自动加上了本地ip的解决方式
一般情况下来说都是一些粗心大意的问题导致的 场景一:少加了/ 场景二:前后多加了空格 场景三:拼接地址错误
Vue3 企业级项目实战:项目须知与课程约定
本节内容很重要,希望大家能够耐心看完。 Vue3 企业级项目实战 - 程序员十三 - 掘金小册Vue3 Element Plus Spring Boot 企业级项目开发,升职加薪,快人一步。。「Vue3 企业级项目实战」由程序员十三撰写,2744人购买https://s.ju…...

传导EMI抑制-Π型滤波器设计
1 传导电磁干扰简介 在开关电源中,开关管周期性的通断会产生周期性的电流突变(di/dt)和电压突变(dv/dt),周期性的电流变化和电压变化则会导致电磁干扰的产生。 图1所示为Buck电路的电流变化,在Buck电路中上管电流和下…...

如何在excel中创建斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:…...

遮挡检测--基于角度的遮挡检测方法
文章目录1基于角度的遮挡检测方法2遮挡检测遍历方法2.1方法1--自适应径向扫描方法2.2方法2--螺旋扫描法参考1基于角度的遮挡检测方法 在基于角度的方法中,通过依次分析DSM中沿径向方向的投影光线的角度来识别遮挡。定义α\alphaα角:DSM三维点与相机中心…...
【luogu CF1098D】Eels(结论)
Eels 题目链接:luogu CF1098D 题目大意 有一个可重集,每次操作会放进去一个数或者取出一个数。 然后每次操作完之后,问你对这个集合进行操作,每次选出两个数 a,b 加起来合并回去,直到集合中只剩一个数,要…...

【java】遍历文件夹输出所有文件的文件名与绝对路径,在windows环境
【java】遍历文件夹输出所有文件的文件名与绝对路径,在windows环境 String filepath "D:\\CloudMusic\\";//D盘下的file文件夹的目录File file new File(filepath);//File类型可以是文件也可以是文件夹File[] fileList file.listFiles();//将该目录下的…...

Window问题详解(下)
建议先看一下 Window问题详解(上) 思路② 既然会超时,那该怎么办呢? 显然需要一个更快速的方法来解决这个问题! 我们先来观察一下图片: 我们发现,每一次选中的数都会增加下一个。 !!!!! 因此,我们可以根据此特性优化时间!! 第一次先求出前 k − 1 k-1 k−...
Kafka部署与SpringBoot集成
Kafka与ZooKeeper Apache ZooKeeper是一个基于观察者模式的分布式服务管理框架,即服务注册中心。同时ZooKeeper还具有存储数据的能力。Kafka的每台服务器作为一个broker注册到ZooKeeper,多个broker借助ZooKeeper形成了Kafka集群。同时ZooKeeper会保存一…...

c++11 标准模板(STL)(std::unordered_set)(十三)
定义于头文件 <unordered_set> template< class Key, class Hash std::hash<Key>, class KeyEqual std::equal_to<Key>, class Allocator std::allocator<Key> > class unordered_set;(1)(C11 起)namespace pmr { templ…...
【2023】DevOps、SRE、运维开发面试宝典之ELKStack相关面试题
文章目录 1、elasticsearch的应用场景2、elasticsearch的特点3、Elasticsearch集群三种状态分别是什么?代表什么?4、Elasticsearch集群的优化方面5、Elasticsearch集群防止脑裂的配置参数?6、ELK日志采集平台架构组件介绍?7、Logstash组件的作用?8、收集Kubernetes集群程序…...

Hive中的高阶函数(二)
1、UDTF之explode函数 explode(array)将array列表里的每个元素生成一行; explode(map)将map里的每一对元素作为一行,其中key为一列,value为一列; 一般情况下,explode函数可以直接使用即可,也可以根据需要结…...
Java集合知识点总结
ArrayListLinkedListLinkedHashSetHashSetTreeSetHashTableHashMapTreeMap是否有序有序有序有序无序自然排序(Comparator)进行排序,默认升序使用的是重写comparTo方法无序无序自动排序元素是否为空可为null可为null不允许可为null不允许键允许…...

培训班出身的同学简历怎么做?面试要注意哪些?来自资深大厂HR的忠告
目录 1 不少培训班候选人的简历中,缺乏足够的商业项目年限 2 直接描述培训班学习经历会带来的负面影响 3 大龄转行Vs年轻的初级程序员,公司一般会如何选择? 4 经过培训班突击后,可以先面试小公司 5 面试官怎么面试有培训班经历…...

Hive3.1.3安装部署_最小化部署_元数据MySQL部署_Hiveserver2部署_metastore部署---大数据之Hive工作笔记0012
hbase 实时分析 hive 离线分析 这里是新版本的hive3.1.3的安装 关于hive的原理之前的博客已经详细说了 可以看到上面是hive运行的原理图 词法分析 语法分析...
javascript:void(0) 含义
我们经常会使用到 javascript:void(0) 这样的代码,那么在 JavaScript 中 javascript:void(0) 代表的是什么意思呢?javascript:void(0) 中最关键的是 void 关键字, void 是 JavaScript 中非常重要的关键字,该操作符指定要计算一个表…...

不用机器学习不用大数据,给你讲通ChatGPT的深层原理
ChatGPT现在看来已经异常火爆了,很多人已经熟知,并且开始练习使用或者开始利用他开始实践了。但仍然有很多人在观望,在疑惑,今天狗哥不用那些高端大气的机器学习亦或是大数据还给你讲通ChatGPT深层到底是个啥逻辑。 目录 1. 聊家…...
JavaScript中的循环类型
JavaScript 中有三种主要的循环类型: for、while 和 do...while。 for: 循环指定次数。 例如: for (let i 0; i < 5; i) {console.log(i); } while: 当条件为真时循环。 例如: let i 0; while (i < 5) {console.log(i);i; } do...while: 先执…...

Spring Boot+Vue前后端分离项目练习02之网盘项目利用token进行登陆验证
1.添加依赖 首先需要添加jwt对应的依赖。 <dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>2.添加配置 JWT由三部分构成,分别是 header, pa…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...