Bootstrap

[剑指OFFER]之搜索算法:JZ44 数字序列中某一位的数字

1.题目

数字以 0123456789101112131415… 的格式作为一个字符序列,在这个序列中第 2 位(从下标 0 开始计算)是 2 ,第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输出第 n 位对应的数字。

2.解法

2.1 题目框架

public class Solution {
  public int findNthDigit (int n) {
        
    }
}

2.2 解法1

对于10以内的数,对应的位置就是n
否则考虑,二位数会占2个位置,所有的两位数占据902个位置, 三位数占3个数位,9003 个位置。依次类推。于是我们实现了一个long count(int level) 方法,根据位数计算占据的的位置。
那么对于 n 是这个序列的下标,那么它是什么数?我们首先要明确n是几位数?那么就用m -= cnt * level;就可以找到是几位数。然后知道了是几位数就简单了。
1、int start = (int) Math.pow(10,level-1);,表示起点。
2、int more = m/level; int offset = m%(level);表示经过了拿哪几个数字,目前停在那个数字的第几位。
3、使用String.valueOf(start+more).charAt(offset)-'0'求解。

 public int findNthDigit(int n) {
        if(n<10) return n;
        // write code here

        n-=10;
        int level = 2;

        int m = n;
        while (true) {
            long cnt = count(level);
            if ( cnt * level > m) break;
            m -= cnt * level;
            level++;
        }

        int start = (int) Math.pow(10,level-1);
        int more = m/level;
        int offset = m%(level);

        return String.valueOf(start+more).charAt(offset)-'0';
    }

    private long count(int level) {
        if (level == 2) return 90;
        return 10 * count(level - 1);
    }

2.3 解法2

与解法1类似。

public int findNthDigit2 (int n) {
        // write code here
        if(n < 10)
            return n;
        n -= 10;
        int digit = 2;
        long num = 10, sum = 90;
        while(n - digit * sum >= 0) {
            n -= digit * sum;
            digit++;
            sum *= 10;
            num *= 10;
        }
        int div = n / digit;
        int mod = n % digit;
        long now = num + div;
        return String.valueOf(now).charAt(mod) - '0';
    }

总结

这个n 是下标,这道题就是要定位 n 在哪个区间。
我们先定位是几位数,比如是3位数,那么就是从100开始的,然后计算偏移量。最后相加即可。

算法系列在github上有一个开源项目,主要是本系列博客的demo代码。https://github.com/forestnlp/alg
如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。

;