Nth Digit

题目地址: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]1999
[10, 99]290180189
[100, 999]390027002889
[1000, 9999]490003600038889
[10000, 99999]590000450000488889
[100000, 999999]690000054000005888889
[1000000, 9999999]790000006300000068888889
[10000000, 99999999]890000000720000000788888889
[100000000, 999999999]99000000008100000000(超出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×10n1

Sn=9×(1+2×10+3×102+4×103++n×10n1)

10Sn=9×(10+2×102+3×103+4×104++n×10n)

以上两式相减:


9Sn=9×(n×10n10n110n2102101)

Sn=n×10n10n110n2102101

Sn=n×10n110n110

这就是countOfDigits的来源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值