[剑指Offer]:数字序列中某一位的数字

146 阅读2分钟

文章目录


题目描述

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。

请写一个函数,求任意第n位对应的数字。

示例 1:

输入:n = 3
输出:3

示例 2:

输入:n = 11
输出:0

题解思路

这道题其实就是找一下规律,同时需要我们细心计算好一些细节,比如位数、余数、索引等。

  1. 找到 n 属于哪个数位里的索引。比如 n = 5,那 n 就是个位这个数位里的索引;或者 n = 11,那 n 就是十位这个数位里的索引。
  2. 确定了 n 属于哪个数位,我们需要进一步定位到 n 具体属于哪个数。比如 n = 11,指的就是 10 这个数。
  3. 确定了 n 属于哪个数,我们就需要算出 n 是这个数的第几位,从而得到最终答案。比如 n = 11,指的是 10 这个数的第 1 位(索引从 0 开始),从而最终答案就是 0。

这里我们定义了几个变量来帮助我们完成上面的三步(代码中对应处也有注释):

  • digit。表示数位,比如个位,digit = 1;十位,digit = 2;百位,digit = 3;以此类推。
  • start。表示该数位的所有数的起始点数。比如个位,start = 1(0 做特例处理,不算在内);十位,start = 10;千位,start = 1000;以此类推。
  • index_count。表示该数位一共有的索引个数。比如个位,index_count = 9(1-9);十位,index_count = 180(10-99);百位,index_count = 2700(100-999);以此类推。我们可以总结出这么一条规律:index_count = digit * 9 * start。比如十位,index_count = 2 * 9 * 10 = 180。

代码实现:

class Solution {
public:
    int findNthDigit(int n) {
        if(n < 0) return -1;
        if(n == 0) return 0;

        int digit = 1;  // 数位(各位/十位/百位... 对应 1/2/3...)
        long start = 1; // 属于该数位的所有数的起点数(个位是1,十位是10,百位是100)
        long index_count = digit * 9 * start;   // 该数位的数一共的索引个数
        
        while(n > index_count){
            // 找出 n 属于哪个数位里的索引
            n -= index_count;
            ++digit;
            start *= 10;
            index_count = digit * 9 * start;
        }
        // 上面的循坏结束后
        // digit 等于原始的 n 所属的数位;start 等于原始 n 所属数位的数的起点
        // index_count 等于原始的 n 所属数位的索引总个数(不重要了,下面不用)
        // n 等于在当前数位里的第 n-1 个索引(索引从 0 算起)
        long num = start + (n-1)/digit; // 得到原始的 n 对应哪个数字
        int remainder = (n-1) % digit;  // 余数就是原始的 n 是这个数字中的第几位

        string s_num = to_string(num);
        return int(s_num[remainder] - '0'); // n 对应着第 remainder 位,再转成 int
    }
};

如有帮助到您,可以多多点赞、评论鼓励哟~~~