Skip to content

Commit 981e864

Browse files
Merge pull request SharingSource#312 from SharingSource/ac_oier
✨feat: Add 382
2 parents 90e4cee + f47e858 commit 981e864

File tree

4 files changed

+143
-0
lines changed

4 files changed

+143
-0
lines changed

Index/模拟.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
| [318. 最大单词长度乘积](https://leetcode-cn.com/problems/maximum-product-of-word-lengths/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-product-of-word-lengths/solution/gong-shui-san-xie-jian-dan-wei-yun-suan-cqtxq/) | 中等 | 🤩🤩🤩🤩 |
3737
| [335. 路径交叉](https://leetcode-cn.com/problems/self-crossing/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/self-crossing/solution/gong-shui-san-xie-fen-qing-kuang-tao-lun-zdrb/) | 困难 | 🤩🤩🤩🤩 |
3838
| [345. 反转字符串中的元音字母](https://leetcode-cn.com/problems/reverse-vowels-of-a-string/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reverse-vowels-of-a-string/solution/gong-shui-san-xie-note-bie-pian-shuang-z-c8ii/) | 简单 | 🤩🤩🤩 |
39+
| [382. 链表随机节点](https://leetcode-cn.com/problems/linked-list-random-node/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/linked-list-random-node/solution/gong-shui-san-xie-xu-shui-chi-chou-yang-1lp9d/) | 中等 | 🤩🤩🤩🤩🤩 |
3940
| [383. 赎金信](https://leetcode-cn.com/problems/ransom-note/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/ransom-note/solution/gong-shui-san-xie-jian-dan-ji-shu-mo-ni-udpzn/) | 简单 | 🤩🤩🤩🤩🤩 |
4041
| [400. 第 N 位数字](https://leetcode-cn.com/problems/nth-digit/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/nth-digit/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-w5wl/) | 中等 | 🤩🤩🤩🤩 |
4142
| [405. 数字转换为十六进制数](https://leetcode-cn.com/problems/convert-a-number-to-hexadecimal/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/convert-a-number-to-hexadecimal/solution/gong-shui-san-xie-yi-ti-shuang-jie-jin-z-d93o/) | 简单 | 🤩🤩🤩🤩 |

Index/蓄水池抽样.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| 题目 | 题解 | 难度 | 推荐指数 |
2+
| ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- |
3+
| [382. 链表随机节点](https://leetcode-cn.com/problems/linked-list-random-node/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/linked-list-random-node/solution/gong-shui-san-xie-xu-shui-chi-chou-yang-1lp9d/) | 中等 | 🤩🤩🤩🤩🤩 |
4+

Index/链表.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
| [146. LRU 缓存机制](https://leetcode-cn.com/problems/lru-cache/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/lru-cache/solution/gong-shui-san-xie-she-ji-shu-ju-jie-gou-68hv2/) | 中等 | 🤩🤩🤩🤩🤩 |
1616
| [203. 移除链表元素](https://leetcode-cn.com/problems/remove-linked-list-elements/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/remove-linked-list-elements/solution/gong-shui-san-xie-yi-chu-lian-biao-yuan-ca6fu/) | 简单 | 🤩🤩🤩 |
1717
| [237. 删除链表中的节点](https://leetcode-cn.com/problems/delete-node-in-a-linked-list/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/delete-node-in-a-linked-list/solution/gong-shui-san-xie-jian-dan-lian-biao-mo-rovcb/) | 简单 | 🤩🤩🤩 |
18+
| [382. 链表随机节点](https://leetcode-cn.com/problems/linked-list-random-node/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/linked-list-random-node/solution/gong-shui-san-xie-xu-shui-chi-chou-yang-1lp9d/) | 中等 | 🤩🤩🤩🤩🤩 |
1819
| [430. 扁平化多级双向链表](https://leetcode-cn.com/problems/flatten-a-multilevel-doubly-linked-list/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/flatten-a-multilevel-doubly-linked-list/solution/gong-shui-san-xie-yi-ti-shuang-jie-di-gu-9wfz/) | 中等 | 🤩🤩🤩🤩🤩 |
1920
| [460. LFU 缓存](https://leetcode-cn.com/problems/lfu-cache/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/lfu-cache/solution/gong-shui-san-xie-yun-yong-tong-pai-xu-s-53m3/) | 困难 | 🤩🤩🤩🤩🤩 |
2021
| [725. 分隔链表](https://leetcode-cn.com/problems/split-linked-list-in-parts/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/split-linked-list-in-parts/solution/gong-shui-san-xie-jing-dian-lian-biao-ju-9yj4/) | 简单 | 🤩🤩🤩🤩🤩 |
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[382. 链表随机节点](https://leetcode-cn.com/problems/linked-list-random-node/solution/gong-shui-san-xie-xu-shui-chi-chou-yang-1lp9d/)** ,难度为 **中等**
4+
5+
Tag :「链表」、「模拟」、「蓄水池抽样」
6+
7+
8+
9+
给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 **被选中的概率一样**
10+
11+
实现 `Solution` 类:
12+
* `Solution(ListNode head)` 使用整数数组初始化对象。
13+
* `int getRandom()` 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等。
14+
15+
示例:
16+
![](https://assets.leetcode.com/uploads/2021/03/16/getrand-linked-list.jpg)
17+
```
18+
输入
19+
["Solution", "getRandom", "getRandom", "getRandom", "getRandom", "getRandom"]
20+
[[[1, 2, 3]], [], [], [], [], []]
21+
22+
输出
23+
[null, 1, 3, 2, 2, 3]
24+
25+
解释
26+
Solution solution = new Solution([1, 2, 3]);
27+
solution.getRandom(); // 返回 1
28+
solution.getRandom(); // 返回 3
29+
solution.getRandom(); // 返回 2
30+
solution.getRandom(); // 返回 2
31+
solution.getRandom(); // 返回 3
32+
// getRandom() 方法应随机返回 1、2、3中的一个,每个元素被返回的概率相等。
33+
```
34+
35+
提示:
36+
* $链表中的节点数在范围 [1, 10^4] 内$
37+
* $-10^4 <= Node.val <= 10^4$
38+
* 至多调用 `getRandom` 方法 $10^4$ 次
39+
40+
41+
进阶:
42+
* 如果链表非常大且长度未知,该怎么处理?
43+
* 你能否在不使用额外空间的情况下解决此问题?
44+
45+
---
46+
47+
### 模拟
48+
49+
由于链表长度只有 $10^4$,因此可以在初始化时遍历整条链表,将所有的链表值预处理到一个数组内。
50+
51+
在查询时随机一个下标,并将数组中对应下标内容返回出去。
52+
53+
代码:
54+
```Java
55+
class Solution {
56+
List<Integer> list = new ArrayList<>();
57+
Random random = new Random(20220116);
58+
public Solution(ListNode head) {
59+
while (head != null) {
60+
list.add(head.val);
61+
head = head.next;
62+
}
63+
}
64+
public int getRandom() {
65+
int idx = random.nextInt(list.size());
66+
return list.get(idx);
67+
}
68+
}
69+
```
70+
* 时间复杂度:令 $n$ 为链表长度,预处理数组的复杂度为 $O(n)$;随机获取某个值的复杂度为 $O(1)$
71+
* 空间复杂度:$O(n)$
72+
73+
---
74+
75+
### 蓄水池抽样
76+
77+
整理题意:总的样本数量未知,从所有样本中抽取若干个,要求每个样本被抽到的概率相等。
78+
79+
具体做法为:**从前往后处理每个样本,每个样本成为答案的概率为 $\frac{1}{i}$,其中 $i$ 为样本编号(编号从 $1$ 开始),最终可以确保每个样本成为答案的概率均为 $\frac{1}{n}$(其中 $n$ 为样本总数)。**
80+
81+
容易证明该做法的正确性,假设最终成为答案的样本编号为 $k$,那么 $k$ 成为答案的充要条件为「在遍历到 $k$ 时被选中」并且「遍历大于 $k$ 的所有元素时,均没有被选择(没有覆盖 $k$)」。
82+
83+
对应事件概率为:
84+
85+
$$
86+
P = \frac{1}{k} * (1 - \frac{1}{k + 1}) * (1 - \frac{1}{k + 2}) * ... * (1 - \frac{1}{n})
87+
$$
88+
89+
首项 $\frac{1}{k}$ 为选中 $k$ 的概率,后面每项分别为编号为 $[k + 1, n]$ 的样本 **不被选中** 的概率。
90+
91+
化简得:
92+
93+
$$
94+
P = \frac{1}{k} * \frac{k}{k + 1} * \frac{k + 1}{k + 2} * ... * \frac{n - 1}{n}
95+
$$
96+
97+
进一步抵消化简后,可得:
98+
$$
99+
P = \frac{1}{n}
100+
$$
101+
102+
因此,在每一次 `getRandom` 时,从前往后处理每个节点,同时记录当前节点的编号,当处理到节点 $k$ 时,在 $[0, k)$ 范围内进行随机,若随机到结果为 $0$(发生概率为 $\frac{1}{k}$),则将节点 $k$ 的值存入答案,最后一次覆盖答案的节点即为本次抽样结果。
103+
104+
代码:
105+
```Java
106+
class Solution {
107+
ListNode head;
108+
Random random = new Random(20220116);
109+
public Solution(ListNode _head) {
110+
head = _head;
111+
}
112+
public int getRandom() {
113+
int ans = 0, idx = 0;
114+
ListNode t = head;
115+
while (t != null && ++idx >= 0) {
116+
if (random.nextInt(idx) == 0) ans = t.val;
117+
t = t.next;
118+
}
119+
return ans;
120+
}
121+
}
122+
```
123+
* 时间复杂度:令 $n$ 为链表长度,随机获取某个值的复杂度为 $O(n)$
124+
* 空间复杂度:$O(1)$
125+
126+
---
127+
128+
### 最后
129+
130+
这是我们「刷穿 LeetCode」系列文章的第 `No.383` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
131+
132+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
133+
134+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
135+
136+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
137+

0 commit comments

Comments
 (0)