From f47e858c989bc7cf2ca841f927f2f3eb4a8a36b2 Mon Sep 17 00:00:00 2001 From: AC_Oier Date: Sun, 16 Jan 2022 08:21:37 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feat:=20Add=20382?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "Index/\346\250\241\346\213\237.md" | 1 + ...64\346\261\240\346\212\275\346\240\267.md" | 4 + "Index/\351\223\276\350\241\250.md" | 1 + ...10\344\270\255\347\255\211\357\274\211.md" | 137 ++++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 "Index/\350\223\204\346\260\264\346\261\240\346\212\275\346\240\267.md" create mode 100644 "LeetCode/381-390/382. \351\223\276\350\241\250\351\232\217\346\234\272\350\212\202\347\202\271\357\274\210\344\270\255\347\255\211\357\274\211.md" diff --git "a/Index/\346\250\241\346\213\237.md" "b/Index/\346\250\241\346\213\237.md" index 5a3e1669..a75619c3 100644 --- "a/Index/\346\250\241\346\213\237.md" +++ "b/Index/\346\250\241\346\213\237.md" @@ -36,6 +36,7 @@ | [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/) | 中等 | 🤩🤩🤩🤩 | | [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/) | 困难 | 🤩🤩🤩🤩 | | [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/) | 简单 | 🤩🤩🤩 | +| [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/) | 中等 | 🤩🤩🤩🤩🤩 | | [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/) | 简单 | 🤩🤩🤩🤩🤩 | | [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/) | 中等 | 🤩🤩🤩🤩 | | [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/) | 简单 | 🤩🤩🤩🤩 | diff --git "a/Index/\350\223\204\346\260\264\346\261\240\346\212\275\346\240\267.md" "b/Index/\350\223\204\346\260\264\346\261\240\346\212\275\346\240\267.md" new file mode 100644 index 00000000..34a95689 --- /dev/null +++ "b/Index/\350\223\204\346\260\264\346\261\240\346\212\275\346\240\267.md" @@ -0,0 +1,4 @@ +| 题目 | 题解 | 难度 | 推荐指数 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- | +| [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/) | 中等 | 🤩🤩🤩🤩🤩 | + diff --git "a/Index/\351\223\276\350\241\250.md" "b/Index/\351\223\276\350\241\250.md" index 25abd083..0beb27e4 100644 --- "a/Index/\351\223\276\350\241\250.md" +++ "b/Index/\351\223\276\350\241\250.md" @@ -15,6 +15,7 @@ | [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/) | 中等 | 🤩🤩🤩🤩🤩 | | [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/) | 简单 | 🤩🤩🤩 | | [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/) | 简单 | 🤩🤩🤩 | +| [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/) | 中等 | 🤩🤩🤩🤩🤩 | | [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/) | 中等 | 🤩🤩🤩🤩🤩 | | [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/) | 困难 | 🤩🤩🤩🤩🤩 | | [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/) | 简单 | 🤩🤩🤩🤩🤩 | diff --git "a/LeetCode/381-390/382. \351\223\276\350\241\250\351\232\217\346\234\272\350\212\202\347\202\271\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/381-390/382. \351\223\276\350\241\250\351\232\217\346\234\272\350\212\202\347\202\271\357\274\210\344\270\255\347\255\211\357\274\211.md" new file mode 100644 index 00000000..0ab7c1e9 --- /dev/null +++ "b/LeetCode/381-390/382. \351\223\276\350\241\250\351\232\217\346\234\272\350\212\202\347\202\271\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -0,0 +1,137 @@ +### 题目描述 + +这是 LeetCode 上的 **[382. 链表随机节点](https://leetcode-cn.com/problems/linked-list-random-node/solution/gong-shui-san-xie-xu-shui-chi-chou-yang-1lp9d/)** ,难度为 **中等**。 + +Tag :「链表」、「模拟」、「蓄水池抽样」 + + + +给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 **被选中的概率一样** 。 + +实现 `Solution` 类: +* `Solution(ListNode head)` 使用整数数组初始化对象。 +* `int getRandom()` 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等。 + +示例: +![](https://assets.leetcode.com/uploads/2021/03/16/getrand-linked-list.jpg) +``` +输入 +["Solution", "getRandom", "getRandom", "getRandom", "getRandom", "getRandom"] +[[[1, 2, 3]], [], [], [], [], []] + +输出 +[null, 1, 3, 2, 2, 3] + +解释 +Solution solution = new Solution([1, 2, 3]); +solution.getRandom(); // 返回 1 +solution.getRandom(); // 返回 3 +solution.getRandom(); // 返回 2 +solution.getRandom(); // 返回 2 +solution.getRandom(); // 返回 3 +// getRandom() 方法应随机返回 1、2、3中的一个,每个元素被返回的概率相等。 +``` + +提示: +* $链表中的节点数在范围 [1, 10^4] 内$ +* $-10^4 <= Node.val <= 10^4$ +* 至多调用 `getRandom` 方法 $10^4$ 次 + + +进阶: +* 如果链表非常大且长度未知,该怎么处理? +* 你能否在不使用额外空间的情况下解决此问题? + +--- + +### 模拟 + +由于链表长度只有 $10^4$,因此可以在初始化时遍历整条链表,将所有的链表值预处理到一个数组内。 + +在查询时随机一个下标,并将数组中对应下标内容返回出去。 + +代码: +```Java +class Solution { + List list = new ArrayList<>(); + Random random = new Random(20220116); + public Solution(ListNode head) { + while (head != null) { + list.add(head.val); + head = head.next; + } + } + public int getRandom() { + int idx = random.nextInt(list.size()); + return list.get(idx); + } +} +``` +* 时间复杂度:令 $n$ 为链表长度,预处理数组的复杂度为 $O(n)$;随机获取某个值的复杂度为 $O(1)$ +* 空间复杂度:$O(n)$ + +--- + +### 蓄水池抽样 + +整理题意:总的样本数量未知,从所有样本中抽取若干个,要求每个样本被抽到的概率相等。 + +具体做法为:**从前往后处理每个样本,每个样本成为答案的概率为 $\frac{1}{i}$,其中 $i$ 为样本编号(编号从 $1$ 开始),最终可以确保每个样本成为答案的概率均为 $\frac{1}{n}$(其中 $n$ 为样本总数)。** + +容易证明该做法的正确性,假设最终成为答案的样本编号为 $k$,那么 $k$ 成为答案的充要条件为「在遍历到 $k$ 时被选中」并且「遍历大于 $k$ 的所有元素时,均没有被选择(没有覆盖 $k$)」。 + +对应事件概率为: + +$$ +P = \frac{1}{k} * (1 - \frac{1}{k + 1}) * (1 - \frac{1}{k + 2}) * ... * (1 - \frac{1}{n}) +$$ + +首项 $\frac{1}{k}$ 为选中 $k$ 的概率,后面每项分别为编号为 $[k + 1, n]$ 的样本 **不被选中** 的概率。 + +化简得: + +$$ +P = \frac{1}{k} * \frac{k}{k + 1} * \frac{k + 1}{k + 2} * ... * \frac{n - 1}{n} +$$ + +进一步抵消化简后,可得: +$$ +P = \frac{1}{n} +$$ + +因此,在每一次 `getRandom` 时,从前往后处理每个节点,同时记录当前节点的编号,当处理到节点 $k$ 时,在 $[0, k)$ 范围内进行随机,若随机到结果为 $0$(发生概率为 $\frac{1}{k}$),则将节点 $k$ 的值存入答案,最后一次覆盖答案的节点即为本次抽样结果。 + +代码: +```Java +class Solution { + ListNode head; + Random random = new Random(20220116); + public Solution(ListNode _head) { + head = _head; + } + public int getRandom() { + int ans = 0, idx = 0; + ListNode t = head; + while (t != null && ++idx >= 0) { + if (random.nextInt(idx) == 0) ans = t.val; + t = t.next; + } + return ans; + } +} +``` +* 时间复杂度:令 $n$ 为链表长度,随机获取某个值的复杂度为 $O(n)$ +* 空间复杂度:$O(1)$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.383` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 +