「每日LeetCode」2022年1月16日
本文最后更新于:2023年3月19日 晚上
- 链表随机节点
382. 链表随机节点
给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点** 被选中的概率一样** 。
实现 Solution 类:
- Solution(ListNode head) 使用整数数组初始化对象。
- int getRandom() 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等。
示例:
输入 [“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, 104] 内
- -104 <= Node.val <= 104
- 至多调用 getRandom 方法 104 次
进阶:
- 如果链表非常大且长度未知,该怎么处理?
- 你能否在不使用额外空间的情况下解决此问题?
思路
蓄水池算法:
具体做法为:从前往后处理每个样本,每个样本成为答案的概率为 i/1 ,其中 i 为样本编号(编号从 1 开始),最终可以确保每个样本成为答案的概率均 1/n(其中 n 为样本总数)。
容易证明该做法的正确性,假设最终成为答案的样本编号为 k,那么 k 成为答案的充要条件为「在遍历到 k 时被选中」并且「遍历大于 k 的所有元素时,均没有被选择(没有覆盖 kk)」。
对应事件概率为:P = 1 / k _ (1 - 1/(k+1)) _ (1 - 1/(k+2)) _ … _ (1 - 1/n)
首项 1 / k 为选中 k 的概率,后面每项分别为编号为 [k + 1, n][k+1,n] 的样本 不被选中 的概率。
化简得:P = 1 / n
作者:AC_OIer
链接:https://leetcode-cn.com/problems/linked-list-random-node/solution/gong-shui-san-xie-xu-shui-chi-chou-yang-1lp9d/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
遍历一次链表,每一次指针指向,就随机生成一个数,如果小于 1/n 说明需要更新 target 到指针指向的 node,同时需要递增 n。
解答
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!