leetcode-第 N 位数字

310 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

题目描述

给你一个整数 n ,请你在无限的整数序列 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...] 中找出并返回第 n 位上的数字。

示例 1:
输入:n = 3
输出:3

示例 2:
输入:n = 11
输出:0
解释:第 11 位数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是 0 ,它是 10 的一部分。
 

提示:

  • 1 <= n <= 231 - 1

思路

首先要理解题意,看了示例2,大概可以看懂,就是每个数字位算1位,返回12345678910111213...这个无限序列的第n位。
理解了题意之后,我们整体思路是,先确定第n位是第x个整数,然后确定是这个整数中的第y位,然后求得这一位。要确定第n位是第x个整数,我们分成2步:

  1. 确定X是个len位数
  2. 确定是len位数的第k个自然数 那如何确定len呢?
    我们尝试找一下规律:
  • len=1,数字是从1~9,总共有9个
  • len=2,数字是从10~99,总共有90个
  • len=3,数字是从100~999,总共有900个 我们似乎找到了规律,按照上面的继续推理,4位数共有9000个,5位数共有90000个,可以不断向后推演。
    其实上述的len位数的自然数个数,是可以通过代数的知识来解的,第1个len位数是10^(len-1),最后1个len位数是10^len-1,所以len位数总共就有10^len-1 - 10^(len-1) + 1 = 9*10^(len-1)个。获取了自然数个数,那len位数总共占用的位数就是len*(9*10^(len-1))。有了这个公式,我们就可以方便的计算出len位数的数字总共占用的位数,我们可以通过循环减的方式,确定len的值,同时,n的余数就是还剩下的偏移。因为len位数的数字,每个都占用len位,可以计算出偏移的k,分成2种情况:
  1. n % len == 0,处理起来最简单,k = n / len,且刚好是这个自然数的最后1位,通过x % 10的方式就可以获取解;
  2. n % len != 0,k = n / len + 1,剩余的位数为n %= len,需要通过(int)(((num + 1) / (long)Math.pow(10, len-n)) % 10)来求解。

Java版本代码

class Solution {
    public int findNthDigit(int n) {
        int len = 1;
        long lenCnt = 9;
        while (n > lenCnt) {
            n -= lenCnt;
            len++;
            lenCnt = 9 * len * (long)Math.pow(10, len - 1);
        }
        long num = (long)Math.pow(10, len - 1) + n / len - 1;
        n %= len;
        if (n == 0) {
            return (int)(num % 10);
        } else {
            return (int)(((num + 1) / (long)Math.pow(10, len-n)) % 10);
        }
    }
}