一、题目:
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
示例 1:
输入:n = 3
输出:3
示例 2:
输入:n = 11
输出:0
限制:0 <= n < 2^31
注意:本题与主站 400 题:400. 第 N 位数字相同。
二、思路和代码:
1、最简单的办法:
从0开始一一枚举,求出它是几位数、累加他之前的数字的所有位数,直到累加数>=n,从这些数字中找出对应的那一位。
//to do
//即使写出来也肯定会因为超时通过不了
2、找规律:
举个例子分析:第1001位是多少???
序列仅有个位数的数为0-9(10位):1001>10,1001不在其中,我们只需要找后面第1001-10=991位即可;
序列接下来仅有两位数的数为10-99(180位):911>180,1001不在其中,我们只需要找后面第991-180=811位即可;
序列接下来仅有两位数的数为100-999(2700位):811<2700,1001在其中!
我们来找2700中第811位是什么,811/3(位数)=270且余数为1,
(需要注意的数每位都是从0开始的而不是1,0、10、100、1000…),所以刚刚100没算进去,所以,第1001位占满了100+269位,还剩余2位(一个是因为0,一个是因为余数),所以这个数应该是370的第二位,7!
计算方法:100+270=370,811就是370的第3-811%3=2位,=7。
我要休息一下!
class Solution {
public:
int findNthDigit(int index) {//主函
if(index < 0)return -1;//废物测试,边界处理,出于健壮性考虑,本题可有可无
int digits = 1;//dights表示 index是几位,默认一位
while(true){
//digits位的数一共有number个
int numbers = countOfIntegers(digits);
//找到indexd 范围 ,1000000000会使得 numbers * digits 溢出int型
if(index < (long long) numbers * digits)return digitAtIndex(index, digits);
index -= digits * numbers;
digits++;
}
return -1;
}
//digits位的数一共有几个
int countOfIntegers(int digits){
return digits == 1?10:9 *pow(10, digits - 1);
}
//找出那个数字num,
int digitAtIndex(int index, int digits){
int num = beginNumber(digits) + index / digits;
int indexFromRight = digits - index % digits;//找到所求的在第几位
for(int i = 1; i < indexFromRight; ++i) num /= 10;
return num % 10;
}
//digits位数的第一个数字
int beginNumber(int digits)
{
return digits == 1?0:pow(10, digits - 1);
}
};
参考剑指offer书中思想,代码:何海涛->剑指offer,
但是,大神在书里面似乎是算错了,想让他退钱!剑指offer第二版P225:
怕什么真理无穷,进一步有进一步的欢喜!