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

相关文章

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

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

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

usaco 1.2 Name That Number(数字字母转化)

巧妙的利用code[b[0]-'A'] 将字符ABC...Z转换为数字 需要注意的是重新开一个数组 c [ ] 存储字符串 应人为的在末尾附上 ‘ \ 0 ’ 详见代码: /*ID: who jayLANG: C++TASK: namenum*/#include<stdio.h>#include<string.h>int main(){FILE *fin = fopen (

uva 10061 How many zero's and how many digits ?(不同进制阶乘末尾几个0)+poj 1401

题意是求在base进制下的 n!的结果有几位数,末尾有几个0。 想起刚开始的时候做的一道10进制下的n阶乘末尾有几个零,以及之前有做过的一道n阶乘的位数。 当时都是在10进制下的。 10进制下的做法是: 1. n阶位数:直接 lg(n!)就是得数的位数。 2. n阶末尾0的个数:由于2 * 5 将会在得数中以0的形式存在,所以计算2或者计算5,由于因子中出现5必然出现2,所以直接一

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

hdu4267区间统计

题意:给一些数,有两种操作,一种是在[a,b] 区间内,对(i - a)% k == 0 的加value,另一种操作是询问某个位置的值。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import

hdu4417区间统计

给你一个数列{An},然后有m次查询,每次查询一段区间 [l,r] <= h 的值的个数。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamRead

hdu3333区间统计

题目大意:求一个区间内不重复数字的和,例如1 1 1 3,区间[1,4]的和为4。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;