2549. 统计桌面上的不同数字

2023-10-17 06:10

本文主要是介绍2549. 统计桌面上的不同数字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

题目

题目分析

解题思路1——暴力破解法

解题思路2—— 解决暴力破解法下空间复杂度太高的问题

解题思路3——解决暴力破解法下时间复杂度过高的问题

解题思路4——时空复杂度为O(1)的算法

总结


题目

给你一个正整数 n ,开始时,它放在桌面上。在 10^9 天内,每天都要执行下述步骤:

  • 对于出现在桌面上的每个数字 x ,找出符合 1 <= i <= n 且满足 x % i == 1 的所有数字 i 。
  • 然后,将这些数字放在桌面上。

返回在 10^9 天之后,出现在桌面上的 不同 整数的数目。

注意:

  • 一旦数字放在桌面上,则会一直保留直到结束。
  • % 表示取余运算。例如,14 % 3 等于 2 。

示例 1:

输入:n = 5
输出:4
解释:最开始,5 在桌面上。 
第二天,2 和 4 也出现在桌面上,因为 5 % 2 == 1 且 5 % 4 == 1 。 
再过一天 3 也出现在桌面上,因为 4 % 3 == 1 。 
在十亿天结束时,桌面上的不同数字有 2 、3 、4 、5 。

示例 2:

输入:n = 3 
输出:2
解释: 
因为 3 % 2 == 1 ,2 也出现在桌面上。 
在十亿天结束时,桌面上的不同数字只有两个:2 和 3 。 

提示:

  • 1 <= n <= 100



题目分析

先来分析一下题目的意思:

题目给定了一个正整数n,作为桌面上最先存在的数字。

题目给定了一个天数:10^9,可以理解为循环的次数。

题目也指明了循环体执行的内容:对于桌面上的每一个数字x,找出一个i满足条件:x % i == 1,i∈[1,n],并将找到的这个i放入桌面。

最后要求返回所有循环结束后,桌面上不同数字的个数。


这边需要注意的是,返回的是桌面上不同数字的个数,也就是说如果将桌面上的这些数放入一个集合中,返回的是集合中元素的个数(因为集合中的元素具有不可重复性)。

tip:返回的不是仅出现一次的数字的个数(题目看快了很容易误以为是这个要求)。




解题思路1——暴力破解法

分析完题目后,题目的意思是很简单的,解题流程大致如下:

但是,这样一来,循环次数固定是10^9次,每次可能会产生若干个符合条件的数字放在桌面上,因此代表桌面的数组array的容量和循环次数是处于一个数量级的,这么一来,加上每次循环还要完整遍历一次数组,这时空复杂度想想就恐怖。

因此它虽然可以得到答案,但是这么做必然会产生时间超限或者空间超限的问题。




解题思路2—— 解决暴力破解法下空间复杂度太高的问题

既然暴力破解法下空间复杂度十分的恐怖,那么必然存在一种方法来降低空间复杂度。

此时想到,返回值等价于将桌面看作一个集合时集合中元素的个数,那么集合中元素具有不可重复性的特点,因此,每次将符合条件的数字放入桌面时,首先判断一下桌面中是否已经存在一摸一样的数字,如果存在便不放入桌面,如果不存在再放入桌面,这样一来,便可以很精确地让桌面符合集合的特性,最后返回桌面中元素的个数即可,因为这样一来桌面上的数字必然是互不相等的。

但是,此时并不知道最后集合的容量是多少,因此这么做的话需要借助一些容量可变的容器来存放数字,或者每次放入的时候进行一次数组扩容。

即便这样,空间复杂度也比暴力破解法下降低了不少。

程序的大致流程如下:




解题思路3——解决暴力破解法下时间复杂度过高的问题

接着进行分析。

上面的思路中,虽然降低了空间复杂度的量级,但是并没有对时间复杂度产生太大的影响,因此必须对题目进行再次分析,以寻找降低时间复杂度的方法。

在上面的思路中,可以发现,如果每次都完整遍历集合时,是存在重复操作的,因为n的值由题目中给出,是一个固定值,因此每一轮循环中,i的范围也是固定的,这就导致每一次遍历集合中在上一轮循环中已经访问的元素时,会得到一样的结果,而这些结果必然不会被放入集合中,因此使用在之前循环中已经访问过的数进行计算必然不会对集合产生任何影响,反而会变成存在了大量的无用计算。因此,在一轮循环中,真正需要进行计算的是集合中没有被访问过的元素。

这样一来,就可以给集合的每一个元素设定一个访问标记,每一轮循环只对集合中未被访问过的元素进行计算,当集合中所有的元素都被访问过时,便结束循环,返回集合中元素的个数。

做到这里,整个算法的时间复杂度和空间复杂度已经较暴力破解法大幅下降了。




解题思路4——时空复杂度为O(1)的算法

接着分析下去,题目中有这样一个表达式:

x % i == 1

那么这个表达式便等价于:

(x - 1) % i == 0

即x-1这个数字可以被i整除,也就是说,x-1必然是i的整数倍,即x必然为i的整数倍+1。

也就是这样:

x = factor * i  + 1      其中,factor∈N,i∈[1,n]

那么,当factor = 0,i = 1时,x可以获得最小值1。

但是,就从上面的等式来看,x貌似是没有上限的,但是深入分析一下x:

x的初始值为n,每一次添加进桌面的元素为符合条件的i,而i∈[1,n],因此x的最小值为1,最大值为n。

因此,x存在一个最大值n。

通过上面的分析,可以十分肯定地确定x的范围:x∈[1,n]。

这个结论很有用,但是现在这个结论是没有办法解题的,因为这个范围十分的准确但并不精确。

对于n=1而言,无论循环多少次,1%1永远只会得到一个0(i=1永远不会满足条件),因此对于n=1而言,x永远只有一个元素1。

对于n=2而言,无论循环多少次,2%1永远只会得到一个0(i=1永远不会满足条件),因此对于n=2而言,x永远不可能为1。

对于n=3而言,无论循环多少次,3%1永远只会得到一个0(i=1永远不会满足条件),因此对于n=3而言,x永远不可能为1。

......

对于任意一个值大于1的n而言,无论循环多少次,n%1永远只会得到一个0(i=1永远不会满足条件),因此对于任意一个大于1的n而言,x永远不可能为1。

因此,精确地表示x的范围为:

那么,当n=1时,桌面上不同整数的数目只有1个。当n≥2时,桌面上不同整数的数目最多有n-1个。

 注意这边使用的是最多,因为此时对于n≥2时的情况,并不能直接获得答案。

下面来分析一下这个结论:

当x=2时,不可能获得任何符合条件的i值。

当x=3时,获得的符合条件的i值为2。(3 % 2 = 1)

当x=4时,获得的符合条件的i值为3。(4 % 3 = 1)

当x=5时,获得的符合条件的i值为4和2。(5 % 4 = 1)(5 % 2 = 1)

...

这样看,好像看不出来什么,那么接下来换一种分析方式:

当x=2时,不可能获得任何符合条件的值。

当x=3时,必定存在一个i=2。

当x=4时,必定存在一个i=3。

当x=5时,必定存在一个i=4。

...

当x=n时,必定存在一个i=x-1。

那么,这个结论很有用,使用这个结论,可以接着向下分析:

对于任意一个x=n(n≥3),必然存在i=x-1。(因为n=2时是不存在任何有效的i的)

对于上面得到的n-1,必然由于n-1≠n而可以被添加入集合,因此必然有x=n-1,而此时必然可以得到一个i=x-1=n-2。

而对于上面得到的n-2,必然由于n-2≠n-1≠n而可以被添加入集合,因此必然有x=n-2,而此时必然可以得到一个i=x-1=n-3。

下面以此类推,可以得到:x={n} => x={n,n-1} => x={n,n-1,n-2} => x={n,n-1,n-2,n-3} => x={n,n-1,n-2,n-3,n-4} => ... => x={n,n-1,n-2,n-3,n-4,...,5} =>  x={n,n-1,n-2,n-3,n-4,...,5,4

} => x={n,n-1,n-2,n-3,n-4,...,5,4,3} => x={n,n-1,n-2,n-3,n-4,...,5,4,3,2}

那么,此时可以确定,当n≥2时,集合中的元素个数必定为n-1个。

综上所述:

 到这一步,这一题的最佳解法便是这一个分段函数,这个结论经过缜密的推导而得出。

因此,这一种解法的时空复杂度为O(1)。




总结

这是力扣第330场周赛的第一题,若是可以快速发现此题中存在的数学关系,便可以在很短的时间内写出正确的题解。若是使用暴力破解法,那么便会存在时空超限的问题。

因此对算法的设计很重要。

这篇关于2549. 统计桌面上的不同数字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/223450

相关文章

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

Java数字转换工具类NumberUtil的使用

《Java数字转换工具类NumberUtil的使用》NumberUtil是一个功能强大的Java工具类,用于处理数字的各种操作,包括数值运算、格式化、随机数生成和数值判断,下面就来介绍一下Number... 目录一、NumberUtil类概述二、主要功能介绍1. 数值运算2. 格式化3. 数值判断4. 随机

java中不同版本JSONObject区别小结

《java中不同版本JSONObject区别小结》本文主要介绍了java中不同版本JSONObject区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1. FastjsON2. Jackson3. Gson4. org.json6. 总结在Jav

Python中连接不同数据库的方法总结

《Python中连接不同数据库的方法总结》在数据驱动的现代应用开发中,Python凭借其丰富的库和强大的生态系统,成为连接各种数据库的理想编程语言,下面我们就来看看如何使用Python实现连接常用的几... 目录一、连接mysql数据库二、连接PostgreSQL数据库三、连接SQLite数据库四、连接Mo

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

从去中心化到智能化:Web3如何与AI共同塑造数字生态

在数字时代的演进中,Web3和人工智能(AI)正成为塑造未来互联网的两大核心力量。Web3的去中心化理念与AI的智能化技术,正相互交织,共同推动数字生态的变革。本文将探讨Web3与AI的融合如何改变数字世界,并展望这一新兴组合如何重塑我们的在线体验。 Web3的去中心化愿景 Web3代表了互联网的第三代发展,它基于去中心化的区块链技术,旨在创建一个开放、透明且用户主导的数字生态。不同于传统