LeetCode 400. Nth Digit
Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...
Note:
n is positive and will fit within the range of a 32-bit signed integer (n < 231).
Example 1:
Input:
3
Output:
3
Example 2:
Input: 11 Output: 0 Explanation: The 11th digit of the sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... is a 0, which is part of the number 10.
题意:将自然数序列看成一个长字符串,给定数字n,判断第n位上的数字是多少。
例:n = 3,第3位上的数字为3(1,2,3);
n = 11,第11位上的数字为0(1,2,3,4,5,6,7,8,9,10. 其中,10中的1为第10位,10中的0为第11位。)
参考:https://www.cnblogs.com/grandyang/p/5891871.html
开始一直没有理解算法中计算目标数字和位数的时候要先对n减1,后来自己举了几个例子才明白。
首先分析自然数序列和其位数的关系,一位的有9个数字(1-9);两位的有90个数字(10-99,可看成排列组合的问题:90 = 9 * 10);三位的有900个数字(100-999,900 = 9 * 10 * 10);依次类推。
以每位数的位数来划分区间,1-9为一个区间,10-99为一个区间,100-999为一个区间,···
变量定义:
count:代表每个区间中有多少个数,例:1-9区间中有9个数;10-99区间中有90个数;100-999区间中有900个数;···因此count初始化为9,每次循环扩大10倍。
len:代表当前区间中数的位数,例:1-9区间中数字的位数为1;10-99区间中数字的位数为2;100-999区间中数字的位数为3;···因此len初始化为1,每次循环加1.
start:代表当前区间的第一个数,例:1-9区间中第一个数为1;10-99区间中第一个数为10;100-999区间中第一个数为100;···因此start初始化为1,每次循环扩大10倍。
思路:先确定n的区间,再确定n位于具体哪个数中,再确定n是该数中的第几位。
在每次循环中用n - len * count(当前区间中的总数字个数),直到n < len * count,则n位于该区间中。
num = start + (n - 1) / len用于判断n位于哪个数中。对(n - 1)的理解(将自然数序列看成坐标,start的第一个数字坐标值为0):
以n = 11为例:
循环一次,n变为:n = 11 - 1 * 9 = 2;
因此n要先减1,再除以len,num = start + (n - 1) / len = 10 + (2 - 1) / 2 = 10;
index = (n - 1) % len用于判断取目标数字中的第几位, 理由同上,index = (n - 1) % len = (2 - 1) % 2 = 1
public int findNthDigit(int n) { long count = 9; int len = 1, start = 1; while(n > len * count) { n -= len * count; len++; count *= 10; start *= 10; } int num = start + (n - 1) / len; int index = (n - 1) % len; return String.valueOf(num).charAt(index) - '0'; }