3步拆解数字序列难题:从LeetCode-Book掌握数位查找核心算法

3步拆解数字序列难题:从LeetCode-Book掌握数位查找核心算法

【免费下载链接】LeetCode-Book 《剑指 Offer》 Python, Java, C++ 解题代码,LeetBook《图解算法数据结构》配套代码仓 【免费下载链接】LeetCode-Book 项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Book

你是否曾在面试中遇到这样的问题:给定一个无限序列1,2,3,...,n,如何快速定位第n位数字?这个看似简单的问题,实则隐藏着对数学规律和算法效率的双重考验。本文将基于LeetCode-Book项目中的经典题型,通过三步拆解法,带你掌握数字序列数位查找的通用解题框架,并提供Python/Java/C++多语言实现方案。

问题定义与数学规律

在开始解题前,我们需要明确几个关键概念:

  • 数位(Digit):数字序列中单个数字字符,如序列"101112..."中的'0'、'1'都是独立数位
  • 数字(Number):由多个数位组成的整数,如10、11、12等
  • 位数(Digit Length):一个数字包含的数位数量,如10是两位数

通过观察可以发现数字序列的分布规律:

  • 1位数(1-9):共9个数字,9×1=9个数位
  • 2位数(10-99):共90个数字,90×2=180个数位
  • 3位数(100-999):共900个数字,900×3=2700个数位

通用公式为:count = 9 × start × digit,其中start是该位数的起始数字(1,10,100...)。这一规律是解题的核心基础,完整推导过程可参考[剑指 Offer 44. 数字序列中某一位的数字.md](https://link.gitcode.com/i/5028a4064437751c88ba9fedcafb5ea2/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/sword_for_offer/docs/剑指 Offer 44. 数字序列中某一位的数字.md?utm_source=gitcode_repo_files)。

三步解题框架

1. 确定目标数位所在数字的位数

通过循环减去不同位数的数位总量,定位目标数位所在数字的位数:

digit, start, count = 1, 1, 9
while n > count:
    n -= count          # 减去当前位数的数位总量
    start *= 10         # 移动到下一位数的起始数字
    digit += 1          # 位数加1
    count = 9 * start * digit  # 计算当前位数的数位总量

这段代码实现了动态调整位数的过程,例如当n=150时:

  • 初始n=150 > 9(1位数总量),减去9后n=141,进入两位数处理
  • 141 > 180(2位数总量)不成立,确定目标在两位数范围内

2. 定位具体数字

确定位数后,计算目标数位所在的具体数字:

long num = start + (n - 1) / digit;

公式推导:

  • start是当前位数的起始数字(如两位数的start=10)
  • (n-1)/digit计算从start开始的偏移量(整数除法)
  • 以n=150为例:n=150-9=141,(141-1)/2=70,num=10+70=80

3. 确定数位位置并返回结果

最后一步是找到数字中的具体数位:

string s = to_string(num);
int res = s[(n - 1) % digit] - '0';

以n=150为例:

  • (141-1)%2=0 → 取数字80的第0位(从0开始计数)
  • '80'的第0位是'8',转化为整数8

完整代码实现

Python实现

class Solution:
    def findNthDigit(self, n: int) -> int:
        digit, start, count = 1, 1, 9
        while n > count:  # 1.确定位数
            n -= count
            start *= 10
            digit += 1
            count = 9 * start * digit
        num = start + (n - 1) // digit  # 2.确定数字
        return int(str(num)[(n - 1) % digit])  # 3.确定数位

Java实现

class Solution {
    public int findNthDigit(int n) {
        int digit = 1;
        long start = 1;
        long count = 9;
        while (n > count) { // 1.确定位数
            n -= count;
            start *= 10;
            digit += 1;
            count = digit * start * 9;
        }
        long num = start + (n - 1) / digit; // 2.确定数字
        return Long.toString(num).charAt((n - 1) % digit) - '0'; // 3.确定数位
    }
}

C++实现

class Solution {
public:
    int findNthDigit(int n) {
        int digit = 1;
        long start = 1;
        long count = 9;
        while (n > count) { // 1.确定位数
            n -= count;
            start *= 10;
            digit += 1;
            count = digit * start * 9;
        }
        long num = start + (n - 1) / digit; // 2.确定数字
        return to_string(num)[(n - 1) % digit] - '0'; // 3.确定数位
    }
};

复杂度分析与优化建议

时间复杂度

  • O(log n):循环次数取决于数字n的位数,最多执行log₁₀n次
  • 数字转字符串操作的时间复杂度为O(digit),而digit = O(log n)

空间复杂度

  • O(log n):主要来自数字转字符串时存储的字符数

优化方向

  1. 避免字符串转换:通过数学运算直接提取数位
    def get_digit(num, index):
        return num // (10 ** (digit - index - 1)) % 10
    
  2. 边界处理:针对n=0等特殊情况增加防御性判断

实际应用与扩展

数位查找算法不仅适用于面试题,还可应用于:

  • 日志系统中的行号定位
  • 大数据处理中的分片索引
  • 密码学中的随机数生成

该算法的核心思想可推广到各类序列定位问题,更多类似题型可参考:

  • [LCR 163. 找到第 k 位数字.md](https://link.gitcode.com/i/5028a4064437751c88ba9fedcafb5ea2/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/leetbook_ioa/docs/LCR 163. 找到第 k 位数字.md?utm_source=gitcode_repo_files)
  • [剑指 Offer 刷题计划.md](https://link.gitcode.com/i/5028a4064437751c88ba9fedcafb5ea2/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/sword_for_offer/剑指 Offer 刷题计划.md?utm_source=gitcode_repo_files)

掌握这种数学建模与分步拆解的思维方式,能帮助你解决更多复杂的算法问题。建议结合项目中的[题目分类.md](https://link.gitcode.com/i/5028a4064437751c88ba9fedcafb5ea2/blob/c12faa39f70b5ddbcd2830db88ac74fea599442b/leetbook_ioa/docs/?utm_source=gitcode_repo_files# 0.2 题目分类.md)进行系统性练习,逐步提升算法设计能力。

总结

本文通过三步法框架,基于LeetCode-Book项目中的经典题型,详细讲解了数字序列数位查找问题的解题思路。关键要点包括:

  1. 利用数学规律动态确定数字位数
  2. 通过整数运算定位目标数字
  3. 高效提取数字中的特定数位

这种解题模式体现了算法设计中的"分而治之"思想,将复杂问题拆解为可管理的小步骤。建议读者尝试修改参数(如n=190、n=1000等)进行测试,深入理解各步骤的计算过程。完整代码与更多解题思路可查阅项目中的sword_for_offer/codes/目录。

关注项目README.md获取最新更新,下期我们将解析"数字序列中的中位数查找"问题,带你进一步拓展算法应用边界。

【免费下载链接】LeetCode-Book 《剑指 Offer》 Python, Java, C++ 解题代码,LeetBook《图解算法数据结构》配套代码仓 【免费下载链接】LeetCode-Book 项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Book

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值