剑指offer(第二版)——数字序列中某一位的数字

PS:《剑指offer》是很多同学找工作都会参考的一本面试指南,同时也是一本算法指南(为什么它这么受欢迎,主要应该是其提供了一个循序渐进的优化解法,这点我觉得十分友好)。现在很多互联网的算法面试题基本上可以在这里找到影子,为了以后方便参考与回顾,现将书中例题用Java实现(第二版),欢迎各位同学一起交流进步。

GitHub: https://github.com/Uplpw/SwordOffer

剑指offer完整题目链接: https://blog.csdn.net/qq_41866626/article/details/120415258

1 题目描述

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

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

leetcode链接: 数字序列中某一位的数字(以下代码已测试,提交通过)

2 测试用例

一般是考虑功能用例,特殊(边缘)用例或者是反例,无效测试用例这三种情况。甚至可以从测试用例寻找一些规律解决问题,同时也可以让我们的程序更加完整鲁棒。

(1)功能用例:n是正数,如5,10等。

(2)边缘用例:n值比较大,如1e6。

(3)无效用例:n<=0。

3 思路

分析:

这道题属于数学规律题,可以举几个例子查找规律,如下:

我们对1位数,2位数,3位数…n位数进行分段,求出各自在数值序列的最大下标。

  • 1 * 9 = 9 # 1位数的最大下标

  • 1 * 9 + 2 * 90 = 189 # 2位数的最大下标

  • 1 * 9 + 2 * 90 + 3 * 900 = 2889 # 3位数的最大下标

  • 1 * 9 + 2 * 90 + 3 * 900 + 4 * 9000 = 38889 # 4 位数的最大下标

所以,n位数的最大下标为 1×9 + 2×90 + 3×900 + … + n×9×10^(n-1)

知道了上面的一点后,开始说说这道题的解题思路:

(1) 首先找到索引为 n 是哪个数的哪一位(例如n=11, 索引为11是10的其中一位)

  • 根据最大下标判断这个数是几位数

    若 n 为 2888,由于 (19 + 290)= 189 < 2888 < (19 + 290 + 3*900)= 2889,所以,这个数是 一个三位数。

  • 根据这个数的位数,就可以求出索引为n是哪个数的第几位

    (2888 - 189)/3 = 899 … 2。所以,这个数是 10^(3-1) + 899 = 999 的第 2 位

    注意:当 n = 2889时,(2889-189)/3 = 900 … 0

    10^(3-1) + 900 = 1000 - 1 = 999 的 第3位。

(2) 获取这个数的第m位
例如 999 的第3位,可以将其转换为字符串,再指定索引即可。

4 代码

算法实现:

public class DigitsInSequence {
    public static int findNthDigit(int n) {
        if (n < 0) {
            return -1;
        }
        // digit :表示 digit 位数
        // max : 表示 dight 位数的最大下标
        // lastMax : 表示 dight - 1 位数的最大下标
        int max = 9, lastMax = 0;
        int digit = 1;
        // 找到这个数是几位数,也就是更新 digit 的过程
        while (n > max) {
            digit++;
            lastMax = max;
            max += digit * 9 * Math.pow(10, digit - 1);
        }
        // 根据这个数的位数,就可以求出索引为n是哪个数的第几位
        int num = (n - lastMax) / digit + (int) Math.pow(10, digit - 1);
        int nth = (n - lastMax) % digit;
        // 特殊情况 余数为0时,更新 nth 为这个数的最后一位
        if (nth == 0) {
            num--;
            nth = digit;
        }
        // 将求出的数 num 转化为 字符串,返回第 nth 位
        return String.valueOf(num).charAt(nth - 1) - '0';

    }

    public static void main(String[] args) {
        System.out.println(findNthDigit(111));
    }
}

参考
在解决本书例题时,参考了一些大佬的题解,比如leetcode上的官方、K神,以及其他的博客,在之后的每个例题详解后都会给出参考的思路或者代码链接,同学们都可以点进去看看!

本例题参考:

  1. leetcode 题解

本文如有什么不足或不对的地方,欢迎大家批评指正,最后希望能和大家一起交流进步、拿到心仪的 offer !!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值