AcWing 57 -- 数学归纳法

题目链接

AcWing 57. 数字序列中某一位的数字

顺序归纳法

1. 确定该数字有多少位

  • 1 1 1 位的数字 0 0 0 ~ 9 9 9 共有 10 10 10
  • 2 2 2 位的数字共有 10 10 10 ~ 99 99 99 共有 90 90 90 * 2 2 2 = 180 180 180
  • 3 3 3 位的数字共有 100 100 100 ~ 999 999 999 900 900 900 * 3 3 3 = 2700 2700 2700

故我们可得:

  • 1 1 1 位的数字共有 10 10 10
  • k k k 位的数字共有 9 9 9 * 1 0 k − 1 10^{k-1} 10k1 * k k k 位, k > 1 k>1 k>1

2. 确定这一位所在数字

现在我们已经知道了数字的位数,那么对于 n n n 位的数字,每隔 n n n 位就是一个 n n n 位数,据此我们就可以得到具体的数字

3. 确定这一位

很简单,具体看代码

代码

注意乘法溢出问题

class Solution {
public:
    int digitAtIndex(int n) {
        int len = 1;    // 数字位数
        long long base = 9, limit = 10; // 注意溢出问题
        // 1. 得到数字的位数
        while(n > limit) {
            len ++ ;
            base *= 10;
            limit += base * len;
        }
        
        // 2. 得到具体的数字
            // n 减去 1~n-1 位所有数字的位数之和,就可以得到 n 位数字的总位数: m = n - (limit - base * len)
            // m / len 即可得到第 n 位所在数字是第几个 n 位数: num = m / len
        int m = n - (limit - base * len);
        int num = m / len + pow(10, len - 1); 
        
        // 3. 计算具体的是数字 num 的哪一位
            // 之前我们已经计算出了 n 位数字的总位数 m 和 数字 num
            // 现在用 m - (num - pow(10, len-1)) * len 即可得到该数字是 num 的哪一位
        int idx = m - (num - pow(10, len - 1)) * len;
        
        return to_string(num)[idx] - '0';
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值