Skip to content

Commit d2d4e2b

Browse files
Merge pull request SharingSource#625 from SharingSource/ac_oier
✨feat: add 剑指 Offer 44
2 parents da57cd7 + 4e269ae commit d2d4e2b

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

Index/数学.md

+1
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,6 @@
7070
| [1720. 解码异或后的数组](https://leetcode-cn.com/problems/decode-xored-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/decode-xored-array/solution/gong-shui-san-xie-li-yong-yi-huo-xing-zh-p1bi/) | 简单 | 🤩🤩🤩 |
7171
| [1734. 解码异或后的排列](https://leetcode-cn.com/problems/decode-xored-permutation/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/decode-xored-permutation/solution/gong-shui-san-xie-note-bie-pian-li-yong-zeh6o/) | 中等 | 🤩🤩🤩🤩 |
7272
| [1738. 找出第 K 大的异或坐标值](https://leetcode-cn.com/problems/find-kth-largest-xor-coordinate-value/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-kth-largest-xor-coordinate-value/solution/gong-shui-san-xie-xiang-jie-li-yong-er-w-ai0d/) | 中等 | 🤩🤩🤩 |
73+
| [剑指 Offer 44. 数字序列中某一位的数字](https://leetcode.cn/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/) | [LeetCode 题解链接](https://leetcode.cn/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/solution/by-ac_oier-wgr8/) | 中等 | 🤩🤩🤩🤩 |
7374
| [面试题 10.02. 变位词组](https://leetcode-cn.com/problems/group-anagrams-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/group-anagrams-lcci/solution/gong-shui-san-xie-tong-ji-bian-wei-ci-de-0iqe/) | 中等 | 🤩🤩🤩🤩 |
7475

Index/模拟.md

+1
Original file line numberDiff line numberDiff line change
@@ -183,5 +183,6 @@
183183
| [面试题 01.05. 一次编辑](https://leetcode.cn/problems/one-away-lcci/) | [LeetCode 题解链接](https://leetcode.cn/problems/one-away-lcci/solution/by-ac_oier-7ml0/) | 中等 | 🤩🤩🤩🤩 |
184184
| [面试题 10.02. 变位词组](https://leetcode-cn.com/problems/group-anagrams-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/group-anagrams-lcci/solution/gong-shui-san-xie-tong-ji-bian-wei-ci-de-0iqe/) | 中等 | 🤩🤩🤩🤩 |
185185
| [面试题 17.11. 单词距离](https://leetcode.cn/problems/find-closest-lcci/) | [LeetCode 题解链接](https://leetcode.cn/problems/find-closest-lcci/solution/by-ac_oier-0hv9/) | 中等 | 🤩🤩🤩🤩 |
186+
| [剑指 Offer 44. 数字序列中某一位的数字](https://leetcode.cn/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/) | [LeetCode 题解链接](https://leetcode.cn/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/solution/by-ac_oier-wgr8/) | 中等 | 🤩🤩🤩🤩 |
186187
| [剑指 Offer II 041. 滑动窗口的平均值](https://leetcode.cn/problems/qIsx9U/) | [LeetCode 题解链接](https://leetcode.cn/problems/qIsx9U/solution/by-ac_oier-g5ha/) | 简单 | 🤩🤩🤩🤩 |
187188

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[剑指 Offer 44. 数字序列中某一位的数字](https://leetcode.cn/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/solution/by-ac_oier-wgr8/)** ,难度为 **中等**
4+
5+
Tag : 「数学」、「模拟」
6+
7+
8+
9+
数字以 `0123456789101112131415…` 的格式序列化到一个字符序列中。在这个序列中,第 $5$ 位(从下标 $0$ 开始计数)是 $5$,第 $13$ 位是 $1$,第 $19$ 位是 $4$,等等。
10+
11+
请写一个函数,求任意第 $n$ 位对应的数字。
12+
13+
示例 1:
14+
```
15+
输入:n = 3
16+
17+
输出:3
18+
```
19+
示例 2:
20+
```
21+
输入:n = 11
22+
23+
输出:0
24+
```
25+
26+
限制:
27+
* $0 <= n < 2^31$
28+
29+
---
30+
31+
### 模拟
32+
33+
我们知道,对于长度为 $len$ 的数字的范围为 $[10^{len - 1}, 10^{len} - 1]$(共 $9 \times 10^{len - 1}$ 个),总长度为:
34+
35+
$$
36+
L = len \times 9 \times 10^{len - 1}
37+
$$
38+
39+
因此我们可以先对 $n$ 进行不断试减(更新 $n$),确定下来目标数字 $x$ 的长度为多少,假设为 $len$。
40+
41+
然后直接计算出长度 $len$ 的最小值为 $s = 10^{len - 1}$,由于范围内的数长度都是 $len$,因此我们可以直接定位到目标数字 $x$ 为何值。
42+
43+
根据目标值 $x$ 必然满足关系式:
44+
45+
$$
46+
(x - s + 1) \times len \geq n
47+
$$
48+
49+
变形可得:
50+
51+
$$
52+
x \geq \left \lfloor \frac{n}{len} \right \rfloor - 1 + s
53+
$$
54+
55+
对 $n$ 进行最后一次的试减(更新 $n$),若恰好有 $n = 0$,说明答案为 $x$ 的最后一位,可由 `x % 10` 取得;若大于 $0$,说明答案是 $x + 1$ 的第 $n$ 位(十进制表示,从左往右数),可由 `(x + 1) / (int) (Math.pow(10, len - n)) % 10` 取得。
56+
57+
代码:
58+
```Java
59+
class Solution {
60+
public int findNthDigit(int n) {
61+
int len = 1;
62+
while (len * 9 * Math.pow(10, len - 1) < n) {
63+
n -= len * 9 * Math.pow(10, len - 1);
64+
len++;
65+
}
66+
long s = (long) Math.pow(10, len - 1);
67+
long x = n / len - 1 + s;
68+
n -= (x - s + 1) * len;
69+
return n == 0 ? (int) (x % 10) : (int) ((x + 1) / Math.pow(10, len - n) % 10);
70+
}
71+
}
72+
```
73+
* 时间复杂度:$O(\log{n})$
74+
* 空间复杂度:$O(1)$
75+
76+
---
77+
78+
### 补充
79+
80+
上述讲解可能对于新手并不友好,尤其是对一些上来只做剑指 Offer 的面试向同学,下面使用更为通俗的方式进行讲解。
81+
82+
对于长度 `len` 的所有数,其最小值为 $10^{len - 1}$,最大值为 $10^{len} - 1$,每个数所能贡献的数的个数为 $len$ 个,因此对于长度为 `len` 的所有数,其所能贡献的数的个数为 $(10^{len} - 10^{len - 1}) \times len$。我们专门开一个函数 `getCnt` 来计算长度为 `len` 的数的个数有多少。
83+
84+
然后我们从 `len = 1` 开始,不断对 `n` 进行试减(`len` 递增),直到 `getCnt(len) <= n` 不再满足。
85+
86+
假设此时的递增到的长度为 `len`,可知长度为 `len` 的最小值 $start = 10^{len - 1}$,我们可以通过计算偏移量 $\left \lfloor \frac{n}{len} \right \rfloor$ 并将其累加到 $start$ 中去,同时对 `n` 进行 $\left \lfloor \frac{n}{len} \right \rfloor \times len$ 的消减。
87+
88+
然后根据 `n` 是否为 $0$ 进行分情况讨论:
89+
90+
*`n` 为 $0$,说明答案落在 $start - 1$ 的最后一位,即 `(start - 1) % 10`
91+
*`n` 不为 $0$,说明答案为 `start` 数值中从左往右数的第 $n$ 位,可通过解法一的方式取得,也可以将其转字符串再通过下标获取。
92+
93+
代码:
94+
```Java
95+
class Solution {
96+
long getCnt(int len) {
97+
return (long)(Math.pow(10, len) - Math.pow(10, len - 1)) * len;
98+
}
99+
public int findNthDigit(int n) {
100+
int len = 1;
101+
while (getCnt(len) <= n) {
102+
n -= getCnt(len);
103+
len++;
104+
}
105+
long start = (long)Math.pow(10, len - 1);
106+
start += n / len;
107+
n -= n / len * len;
108+
if (n == 0) return (int)(start - 1) % 10;
109+
else return String.valueOf(start).toCharArray()[n - 1] - '0';
110+
}
111+
}
112+
```
113+
* 时间复杂度:$O(\log{n})$
114+
* 空间复杂度:$O(1)$
115+
116+
---
117+
118+
### 最后
119+
120+
这是我们「刷穿 LeetCode」系列文章的第 `No.剑指 Offer 44` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
121+
122+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
123+
124+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
125+
126+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
127+

0 commit comments

Comments
 (0)