题目地址:https://leetcode.com/problems/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
).
首先看下自然数及其对应位数的情况:
数字区间 | 位数 | 数字数目 | 位数总数 | 该区间(包括该区间)以前的位数总数 |
---|---|---|---|---|
[1, 9] | 1 | 9 | 9 | 9 |
[10, 99] | 2 | 90 | 180 | 189 |
[100, 999] | 3 | 900 | 2700 | 2889 |
[1000, 9999] | 4 | 9000 | 36000 | 38889 |
[10000, 99999] | 5 | 90000 | 450000 | 488889 |
[100000, 999999] | 6 | 900000 | 5400000 | 5888889 |
[1000000, 9999999] | 7 | 9000000 | 63000000 | 68888889 |
[10000000, 99999999] | 8 | 90000000 | 720000000 | 788888889 |
[100000000, 999999999] | 9 | 900000000 | 8100000000(超出int类型的范围) | 2036372536 |
[1000000000, 2147483647] | 10 | …… | …… | …… |
因为n是一个32位的有符号正整数,其对应的最大值是2147483647,所以列到这里差不多了。
所以我们根据上面的表格可以按照区间区求n对应多少位,这样就会快不少,n确定了具体的区间,然后再根据区间内数字的位长度在区间内确定到底是哪个数字,最后进一步确定是数字的哪一位即可:
/**
* 9
* 189
* 2889
* 38889
* 488889
* 5888889
* 68888889
* 788888889
* 2036372536
*/
public class NthDigit {
public static int countOfDigits(int n) {
return (int)(n * Math.pow(10, n)) - (int)((Math.pow(10, n) - 1) / 9);
}
public static int fnd(int n, int startNumber, int start, int digits) {
if ((n - start) % digits == 0) {
int k = startNumber + (n - start) / digits - 1;
return k % 10;
} else {
int k = startNumber + (n - start) / digits;
return (k / (int)(Math.pow(10, digits - (n - start) % digits))) % 10;
}
}
public static int findNthDigit(int n) {
if (n <= 9) {
// All numbers have 1 digit for each. [1, 9]
return n;
} else if (n > 9 && n <= 189) {
// All numbers have 2 digits for each. [10, 99]
return fnd(n, 10, 9, 2);
} else if (n > 189 && n <= 2889) {
// All numbers have 3 digits for each. [100, 999]
return fnd(n, 100, 189, 3);
} else if (n > 2889 && n <= 38889) {
// All numbers have 4 digits for each. [1000, 9999]
return fnd(n, 1000, 2889, 4);
} else if (n > 38889 && n <= 488889) {
// All numbers have 5 digits for each. [10000, 99999]
return fnd(n, 10000, 38889, 5);
} else if (n > 488889 && n <= 5888889) {
// All numbers have 6 digits for each. [100000, 999999]
return fnd(n, 100000, 488889, 6);
} else if (n > 5888889 && n <= 68888889) {
// All numbers have 7 digits for each. [1000000, 9999999]
return fnd(n, 1000000, 5888889, 7);
} else if (n > 68888889 && n <= 788888889) {
// All numbers have 8 digits for each. [10000000, 99999999]
return fnd(n, 10000000, 68888889, 8);
} else {
// All numbers have 9 digits for each. [100000000, 999999999]
return fnd(n, 100000000, 788888889, 9);
}
}
public static void main(String[] args) {
for (int i = 1; i < 300; i++) {
System.out.print(findNthDigit(i));
}
}
}
方法countOfDigits是计算表格最后一列的一个方法,具体推导如下:
Sn=9+2×90+3×900+4×9000+⋯⋯+n×9×10n−1⇒
Sn=9×(1+2×10+3×102+4×103+⋯⋯+n×10n−1)⇒
10Sn=9×(10+2×102+3×103+4×104+⋯⋯+n×10n)⇒
以上两式相减:
9Sn=9×(n×10n−10n−1−10n−2−⋯⋯−102−10−1)⇒
Sn=n×10n−10n−1−10n−2−⋯⋯−102−10−1⇒
Sn=n×10n−1−10n1−10
这就是countOfDigits的来源。