题目:数字以 012345678912131415… 的格式序列化到一个字符序列中。在这个序列中,第 5 位(从 0 开始计数)是 5,第 13 位是 1,第 19 位是 4,等等。请写一个函数,求任意第 n 位对应的数字。
思路 1:穷举
最直接的思路是:从 0 开始逐个枚举数字,累加数字的位数:当位数小于 n 时,继续枚举数字;当位数等于或大于 n 时,则说明该数字中的某一位就是第 n 位对应的数字,然后找出其中所对应的那一位数字。
这个算法是极为简单的思路,时间复杂度可能达不到面试官的要求,我们还需要思考更快的算法。
思路 2:分析例子找规律
我们一定要从 0 开始一个一个枚举数字吗?不一定。在到我们想要的数字之前,很多数字都是可以忽略的。基于这个想法,我们来分析具体的例子,看看如何忽略大部分不需要枚举的数字。为了说清楚这个算法,我们取 n=1001。因此,我们需要找出第 1001 位对应的数字。
- 0~9 这 10 个数字是一位数,$1001-10=991 \geq 0$,因此我们可以忽略这 10 个数字。我们从其后搜索第 991 位
- 10~99 这 90 个数字是二位数,$991-90*2=811 \geq 0$,因此我们也可以忽略这 90 个数字。我们从其后搜索第 811 位
- 100~999 这 900 个数字是三位数,$811-900*3=-1889<0$,因此我们要找的数字肯定是出现在 100~999 中。
- 由于 $811=270*3+1$,因此我们要找的数字是在 100~999 中的第 270 个(从 0 开始计数)数的第 1 位(从 0 开始计数),所以 1001 位对应的数字是 7(370 中的中间一位)
根据以上例子的分析,我们可以将思路进行总结:首先找出是几位数,然后找出是哪个数,最后找出是这个数中的第几位。这个算法的时间复杂度小于 $O(log\,n)$,明显快于上一种算法。