LeetCode 400. Nth Digit

Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ...

Note:
n is positive and will fit within the range of a 32-bit signed integer (n < 231).

Example 1:

Input:
3
Output:
3

Example 2:

Input:
11
Output:
0

Explanation:
The 11th digit of the sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... is a 0, which is part of the number 10.

题意:将自然数序列看成一个长字符串,给定数字n,判断第n位上的数字是多少。
例:n = 3,第3位上的数字为3(1,2,3);
n = 11,第11位上的数字为0(1,2,3,4,5,6,7,8,9,10. 其中,10中的1为第10位,10中的0为第11位。)

参考:https://www.cnblogs.com/grandyang/p/5891871.html

开始一直没有理解算法中计算目标数字和位数的时候要先对n减1,后来自己举了几个例子才明白。

 

首先分析自然数序列和其位数的关系,一位的有9个数字(1-9);两位的有90个数字(10-99,可看成排列组合的问题:90 = 9 * 10);三位的有900个数字(100-999,900 = 9 * 10 * 10);依次类推。
以每位数的位数来划分区间,1-9为一个区间,10-99为一个区间,100-999为一个区间,···
变量定义:
count:代表每个区间中有多少个数,例:1-9区间中有9个数;10-99区间中有90个数;100-999区间中有900个数;···因此count初始化为9,每次循环扩大10倍。

len:代表当前区间中数的位数,例:1-9区间中数字的位数为1;10-99区间中数字的位数为2;100-999区间中数字的位数为3;···因此len初始化为1,每次循环加1.

start:代表当前区间的第一个数,例:1-9区间中第一个数为1;10-99区间中第一个数为10;100-999区间中第一个数为100;···因此start初始化为1,每次循环扩大10倍。

思路:先确定n的区间,再确定n位于具体哪个数中,再确定n是该数中的第几位。


在每次循环中用n - len * count(当前区间中的总数字个数),直到n < len * count,则n位于该区间中。
num = start + (n - 1) / len用于判断n位于哪个数中。对(n - 1)的理解(将自然数序列看成坐标,start的第一个数字坐标值为0):
以n = 11为例:
循环一次,n变为:n = 11 - 1 * 9 = 2;

因此n要先减1,再除以len,num = start + (n - 1) / len = 10 + (2 - 1) / 2 = 10;

index = (n - 1) % len用于判断取目标数字中的第几位, 理由同上index = (n - 1) % len = (2 - 1) % 2 = 1

public int findNthDigit(int n) {
        long count = 9;
        int len = 1, start = 1;  
        while(n > len * count) {  
            n -= len * count;
            len++;
            count *= 10;
            start *= 10;
        }
        int num = start + (n - 1) / len;
        int index = (n - 1) % len;
        return String.valueOf(num).charAt(index) - '0';  
    }

 

 

posted @ 2018-01-09 15:46  zeroingToOne  阅读(125)  评论(0编辑  收藏  举报