剑指 Offer 44. 数字序列中某一位的数字
思路:找规律
数字范围 | 数字位数 | 数字数量 | 数位数量 |
0-9 | 1 | 10 | 10 |
10-99 | 2 | 90 | 180 |
100-999 | 3 | 900 | 2700 |
…… | …… | …… | …… |
start-end | digit | 9*start | 9*start*digit |
由此,要得到第n位对应的数字,需要分三步:
1. 确定 n 所在数字 num 的位数 digit;
记录当前数字位数对应的数位总和count,n 不断减去上一个位数的数位总和。
当 n ≤ count 时,确定 n 所在数字 num 的位数 digit;
2. 确定 num;
记录当前数字位数对应的数字范围左边界 start,num = start + n / digit;
3. 确定 n 是 num 中的哪一位,返回结果。
n 在num中的位数等于 n % digit。
将数字 num 转换成字符数组,使用charAt()-‘0’得到结果。
代码:
时间复杂度O(logn):
所求数位 n 对应数字 num 的位数 digit 最大为 O(logn) ;第一步最多循环 O(logn) 次;第三步中将 num 转化为字符串使用 O(logn) 时间;因此总体为 O(logn) 。
空间复杂度O(logn):
将数字 num 转化为字符串 str(num)
,占用 O(logn) 的额外空间。
class Solution { public int findNthDigit(int n) { //初始化 if (n < 10) return n; int digit = 1;//位数 long start = 1;//每个digit开始的数字 long count = 10;//在digit位数中数位的数量,如1位数有10个(从0开始),2位数有90个 while (n > count) { n -= count;//减去上一个位数的数位总和 digit++; start *=10; count = 9 * start * digit; } //求n所在数字num long num = start + n / digit;//此时的n减去了小于它的位数总和 int i = n % digit;//得到n在num中的位数 return Long.toString(num).charAt(i) - '0';//long型转string,charAt得到第i位字符型数字,减‘0’得到对应数字 } }