刷题的日子2023.3.1

一些感想

从前天(2023.2.27)开始刷题,刷题的网站是牛客和力扣。在刷题过程中遇到过很多知识点,有的是原本掌握一些但是存在疏漏的,有的是从未见过的新知识,有的是从前掌握了但是仍然忘记的……
这样的情况发生过几次后,我发现如果靠着我自己的脑子记下庞大的知识点集,那么脑子几乎是不够用的。因此我建立了这篇文章,希望以此作为我需要注意的的知识点的记录。
由于第一天和第二天我没能想起来这个办法,在第三天也就是今天还记录前两天的话,我难免会感到任务繁重并因此懈怠,我就从这一天开始记录了,前两天的内容我会不定期地在某处添加上,也许不会添加,管它呢。但我保证接下来每天都会对我的刷题日程进行记录!
接下来就开始记录了~

NC291 数字序列中某一位的数字描述

题目描述

数字以 0123456789101112131415… 的格式作为一个字符序列,在这个序列中第 2 位(从下标 0 开始计算)是 2 ,第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输出第 n 位对应的数字。

数据范围: 0≤n≤109 0≤n≤109

前言

这个题目我是前一天晚上做的,当时用了把每个数字都转换成字符串再添加到一个总串上面的方法。共七个用例,运行到第六个的时候提示超出时间限制。当时时间比较晚,再加上头昏脑涨,就上床休息了,今天继续攻克这道题。未果,看解答区的解答。

思路

设置以下变量,并初始化,值如下:

  • int digit=1; 用于记录当前区间,数字的位数是几位
  • long start=1; 用于记录此区间的第一个数字的值
  • long sum=9; 用于记录到目前区间最大的数字为止,共有几位数字

注:start要用long,如果用int那么测试数字过大时会出现错误
接下来是定位n所在的区间

while(n>sum)
{
    n-=sum;
    digit++;//过了该区间,数字位数增大1
    start=start*10;//新区间开始的数字,1—10—100—1000—10000
    sum=9*start*digit;//从新区间开始,到新区间的最大数字为止,一共有几位
}

到这个循环结束,我们就求出了n所在的区间。
注意:n也是在不断更新的,每次循环n都要减去上个区间的所有位数。
接下来的代码就是求出来n所在的具体数字了。

int num = start + (n - 1) / digit;

之所以这么算,是因为此时的n,已经成为了所求位数在当前区间是第几位数字。之所以要减一,是因为我们的程序是从1开始算的,而题目是从0开始算的第一位。
我们为什么从1开始而不是从0开始呢,请注意这条代码:

start=start*10; //新区间开始的数字,1—10—100—1000—10000

这条代码计算新区间开始的数字,如果是0,那么就没办法算了。

接下来要求的就是n所在的具体数字的具体哪一位了。

int index = (n-1) % digit;//计算在哪一位

之所以要减一原因如上,因为我们的程序是从1开始的,而题目是从0开始的。

最后的返回语句:

return to_string(num)[index]-'0';

解释:num转换成字符串,根据索引index找到对应字符,而要减去’0’的原因是,字符类型的’1’—'9’对应的不是数字1—9,减去字符’0’后,值才等于数字。

再见

今天就练了一道题,挺少的,但是今天有两个笔试,精疲力尽。再见了,也许是暂时再见,等会还会练一道题;也许是明天再见,今天不再练题了,而是忙那该死的毕业论文;也许两者都不是,而是我躺在了床上。
总之,拜拜~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值