概述
给你一个整数 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
- 第
n
位上的数字是按计数单位(digit)从前往后数的第n
个数,参见 示例 2 。
解题思路
为了得到无限整数序列中的第 n 位数字,需要知道第 n 位数字是哪一个整数的第几位。如果知道第 n 位数字所在整数是几位数,就能计算得到第 n 位数字是哪一个整数的第几位。
假设第 n 位数字所在整数是 d 位数,则所有位数不超过 d - 1 的整数的位数之和小于 n,且所有位数不超过 d 的整数的位数之和大于等于 n。由于所有位数不超过 x 的整数的位数之和关于 x 单调递增,因此可以使用二分查找确定上述 d 的值。对于某个 x,如果所有位数不超过 x 的整数的位数之和小于 n,则 d > x,否则 d <= x,以此调整二分查找的上下界。
由于任何整数都至少是一位数,因此 d 的最小值是 1。对于 d 的上界,可以通过找规律的方式确定。
- 1 位数的范围是 1 到 9,共有 9 个数,所有 1 位数的位数之和是 1 * 9 = 9。
- 2 位数的取值范围是 10 到 99,共有 90 个数,所有 2 位数的位数之和是 2 * 90 = 180。
- 3 位数的取值范围是 100 到 999,共有 900 个数,所有 3 位数的位数之和是 3 × 900 = 2700。
- ……
推广到一般情形,x 位数的范围是 10^x - 1^ 到 10x - 1,共有 10x - 1 - 10^x - 1^ + 1 = 9 * 10^x - 1^ 个数,所有 x 位数的位数之和是 x * 9 * 10^x - 1^ 。
由于 n 的最大值为 231 - 1 ,约为 2 * 109 ,当 x = 9 时,x * 9 * 10^x - 1^ = 8.1 * 109 > 231 - 1 ,因此第 n 位数字所在整数最多是 9 位数,令 d 的上界为 9 即可。
在得到 d 的值之后,可以根据上述规律计算得到所有位数不超过 d - 1 的整数的位数之和,然后得到第 n 位数在所有 d 位数的序列中的下标,为了方便计算,将下标转换成从 0 开始记数。具体而言,用 prevDigits 表示所有位数不超过 d - 1 的整数的位数之和,则第 n 位数在所有 d 位数的序列中的下标是 index = n - prevDigits - 1,index 的最小可能取值是 0。
得到下标 index 之后,可以得到无限整数序列中的第 n 位数字是第 ⌊ index / d ⌋ 个 d 位数的第 index mod d 位,注意编号都从 0 开始。
由于最小的 d 位数是 10^d - 1^ ,因此第 n 位数字所在的整数是 10^d - 1^ +⌊index / d⌋,该整数的右边第 d - (index mod d) - 1 位(计数从 0 开始)即为无限整数序列中的第 n 位数字。
代码
// 400. 第 N 位数字
func findNthDigit(_ n: Int) -> Int {
func totalDigits(_ length: Int) -> Int {
var digits = 0, curLength = 1, curCount = 9
while curLength <= length {
digits += curLength * curCount
curLength += 1
curCount *= 10
}
return digits
}
var low = 1, high = 9
while low < high {
let mid = (high - low) / 2 + low
if totalDigits(mid) < n {
low = mid + 1
} else {
high = mid
}
}
let d = low
let prevDigits = totalDigits(d - 1)
let index = n - prevDigits - 1
let start = Int(pow(10.0, Double(d - 1)))
let num = start + index / d
let digitIndex = index % d
let digit = (num / Int(pow(10.0, Double(d - digitIndex - 1)))) % 10
return digit
}
最后
以上就是复杂指甲油为你收集整理的iOS LeetCode ☞ 第 N 为数字的全部内容,希望文章能够帮你解决iOS LeetCode ☞ 第 N 为数字所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复