【剑指 2】面试题 44:数字序列中某一位的数字

题目:

数字以 0123456789101112131415... 的格式序列化到一个字符序列中。在这个序列中,第 5 位(从 0 开始计数)是 5,第 13 位是 1,第 19 位是 4,等等。写出一个函数,求任意第 n 位对应的数字。

解题思路:

题目中的序列,存在一个规律:

即依次由一位的数字,两位的数字,三位的数字,X 位的数字,对应的数字序列从小到大,拼接而成。

第 0 至第 10 位由只有一位的数字,即 [0, 9] 组成,共 10 个数字,在序列中共占 10*1=10 位;
第 11 至第 190 位由只有两位的数字,即 [10, 99] 组成,共 90 个数字,在序列中共占 90*2=180 位;
第 191 至第 2890 由只有三位的数字,即 [100,999] 组成,共 900 个数字,在序列中共占 900*3=2700 位;

依次类推。

可以看到规律,对于序列的第 n 位,肯定对应只有 X 位的数字 序列中的某一个数的某一位,即 [10 x-1, 10x-1] 中的某一个数的某一位。

求出 X 之后,且 n 减去由一位数,二位数,(X - 1) 数这些数字所占的位数,剩下的即位只有 X 位的数字所占的位数,假设位 ByteX,此时就可以知道 ByteX 对应多少个只有 X 位的数字,

Byte / X = Y ... index,其中 Y 位商,index 为余数,且 Y 即对应目标数在只有 X 位数中的序列位置,index 即对应具体的那一位,即 n 对应的数字。

具体的代码实现:

private static int method(int n) {
    if (n < 0) {
        return -1;
    }
    if (n < 11) {
        return n - 1;
    }
    
    int Byte = n;
    int X = 1;
    double tmp = 10;// 只有一位的数字共占 10 位
    while (Byte - tmp > 0) {
        ++X;
        Byte -= tmp;
        // 只有 X 位所有数字在序列中共占 (Math.pow(10, X) - Math.pow(10, X - 1)) * X 位
        tmp = (Math.pow(10, X) - Math.pow(10, X - 1)) * X;
    }
    
    // 求出 n 对应的是几位数,假设 X 为 2,则是 n 处于两位数的序列中
    // 而两位数是从 10 开始
    double base = Math.pow(10, X - 1);
    
    // 求出在两位数序列中的第 Y 个序列位,
    // 比如 n = 19 时, X 位 2,即第 n 位是位于两位数的序列中,即在 101112131415... 中
    // 此时 Byte 位 9,表示是 101112131415... 的第九位
    // 但是不能直接求出,因此要求出第 9 位对应的序列数,即 (9/(X = 2)) 结果为 4,余 1
    // 即对应 10+4 = 14 的第 1 位(第 0 位为 1,第 1 位为 4)
    int Y = Byte  / X;
    int index = Byte % X;
    double number = base + Y;
    
    // 这一步就是求出序列数 14 的第 1 位,即用 14 / 10,使 4 处于个位,再取余即可
    int result = (int) ((number / Math.pow(10, X - index - 1)) % 10);
    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值