描述

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

数据范围: 0≤n≤10^9

示例
// 输入
0
// 输出
0

// 输入
2
// 输出
2

// 输入
10
// 输出
1

// 输入
13
// 输出
1
解题思路
// 区间规律
0
1 ~ 9:1 * 9 = 9
10 ~ 99:2 * 90 = 180
100 ~ 999:3 * 900 = 2700
...

// n 属于哪个自然数
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
n   - 区间首位 - 位数 - 所属自然数 - 下标
2   -   1    -  1  -  2=1+(2-1)/1      -   0=(2-1)%1
10  -   10   -  2  -  10=10+(10-9-1)/2  -   0=(10-9-1)%2
13  -   10   -  2  -  11=10+(13-9-1)/2  -   1=(13-9-1)%2

所属自然数 = 区间首位数 + 剩余部分除以这个区间的位数

从以上示例可以发现 n-1 和区间之间的规律

位数:digit
区间首位:start
区间总位数:sum = digit * 9 * start
区间剩余部分:x
所属自然数:start + (x-1)/digit
  • 确定 n 属于哪个区间

    • 通过 n 不断减去前面区间的位数
  • 确定 n 属于哪个自然数

    • 区间首位数 + 剩余部分 / 这个区间的位数
  • 确定 n 在自然数中的位置

    • n - 1 对这个位数取模
代码实现
/**
 * [JZ44-简单] 数字序列中某一位的数字
 *
 * @param data int 整型一维数组
 * @param k int 整型
 * @return int 整型
 */
func findNthDigit(n int) int {
    // 位数、区间首位数字、区间总位数
    digit, start, sum := 1, 1, 9

    // 获取位数、区间首位、区间总位数
    for n > sum {
        n -= sum
        start *= 10
        digit += 1
        sum = 9 * start * digit
    }

    // 定位 n 在哪个数上
    num := start + (n-1)/digit

    // 定位 n 在这个数的哪一位上
    index := (n - 1) % digit

    // 将 num 转化成 string
    numStr := strconv.Itoa(num)

    // 根据 index 索引获取字符串值
    numStr = string(numStr[index])

    // 将字符串转化成 int
    ret, _ := strconv.Atoi(numStr)

    return ret
}

本文由 一切随风 创作,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论