comments: true
difficulty: 中等
edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9844.%20%E6%95%B0%E5%AD%97%E5%BA%8F%E5%88%97%E4%B8%AD%E6%9F%90%E4%B8%80%E4%BD%8D%E7%9A%84%E6%95%B0%E5%AD%97/README.md
面试题 44. 数字序列中某一位的数字
题目描述
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
示例 1:
输入:n = 3 输出:3
示例 2:
输入:n = 11 输出:0
限制:
0 <= n < 2^31
注意:本题与主站 400 题相同:https://leetcode.cn/problems/nth-digit/
解法
方法一:数学
【LeetCode力扣刷题 | 剑指Offer题解合集 | 画解算法思路Python3或C++代码实现】 https://www.bilibili.com/video/BV1CK411c7gx/?p=39&share_source=copy_web&vd_source=ed4a51d52f6e5c9a2cb7def6fa64ad6a
位数为 k k k 的最小整数和最大整数分别为 1 0 k − 1 10^{k-1} 10k−1 和 1 0 k − 1 10^k-1 10k−1,因此 k k k 位数的总位数为 k × 9 × 1 0 k − 1 k \times 9 \times 10^{k-1} k×9×10k−1。
我们用 k k k 表示当前数字的位数,用 c n t cnt cnt 表示当前位数的数字的总数,初始时 k = 1 k=1 k=1, c n t = 9 cnt=9 cnt=9。
每次将 n n n 减去 c n t × k cnt \times k cnt×k,当 n n n 小于等于 c n t × k cnt \times k cnt×k 时,说明 n n n 对应的数字在当前位数的数字范围内,此时可以计算出对应的数字。
具体做法是,首先计算出 n n n 对应的是当前位数的哪一个数字,然后计算出是该数字的第几位,从而得到该位上的数字。
时间复杂度 O ( log 10 n ) O(\log_{10} n) O(log10n),空间复杂度 O ( 1 ) O(1) O(1)。其中 n n n 为给定的数字。
Python3
class Solution:
def findNthDigit(self, n: int) -> int:
k, cnt = 1, 9
# 1) K:确定是 几位数
while k * cnt < n: #9 9*10*2 9*100*3 ...
n -= k * cnt
k += 1
cnt *= 10
# 2)start: 10 ** (k - 1) -> 确定 几位数范围内 对应 具体那个数
num = 10 ** (k - 1) + (n - 1) // k
# 3)在具体那个数 中 取对应位的数
idx = (n - 1) % k # 计算对应的位
return int(str(num)[idx])
Java
class Solution {
public int findNthDigit(int n) {
int k = 1, cnt = 9;
while ((long) k * cnt < n) {
n -= k * cnt;
++k;
cnt *= 10;
}
int num = (int) Math.pow(10, k - 1) + (n - 1) / k;
int idx = (n - 1) % k;
return String.valueOf(num).charAt(idx) - '0';
}
}
C++
class Solution {
public:
int findNthDigit(int n) {
int k = 1, cnt = 9;
while (1ll * k * cnt < n) {
n -= k * cnt;
++k;
cnt *= 10;
}
int num = pow(10, k - 1) + (n - 1) / k;
int idx = (n - 1) % k;
return to_string(num)[idx] - '0';
}
};
Go
func findNthDigit(n int) int {
k, cnt := 1, 9
for k*cnt < n {
n -= k * cnt
k++
cnt *= 10
}
num := int(math.Pow10(k-1)) + (n-1)/k
idx := (n - 1) % k
return int(strconv.Itoa(num)[idx] - '0')
}
JavaScript
/**
* @param {number} n
* @return {number}
*/
var findNthDigit = function (n) {
let k = 1,
cnt = 9;
while (k * cnt < n) {
n -= k * cnt;
++k;
cnt *= 10;
}
const num = Math.pow(10, k - 1) + (n - 1) / k;
const idx = (n - 1) % k;
return num.toString()[idx];
};
C#
public class Solution {
public int FindNthDigit(int n) {
int k = 1, cnt = 9;
while ((long) k * cnt < n) {
n -= k * cnt;
++k;
cnt *= 10;
}
int num = (int) Math.Pow(10, k - 1) + (n - 1) / k;
int idx = (n - 1) % k;
return num.ToString()[idx] - '0';
}
}
Swift
class Solution {
func findNthDigit(_ n: Int) -> Int {
var n = n
var k = 1
var count = 9
while k * count < n {
n -= k * count
k += 1
count *= 10
}
let num = Int(Double(10).power(Double(k - 1))) + (n - 1) / k
let idx = (n - 1) % k
let numString = String(num)
let char = numString[numString.index(numString.startIndex, offsetBy: idx)]
return char.wholeNumberValue!
}
}
extension Double {
func power(_ exponent: Double) -> Double {
return pow(self, exponent)
}
}