「每日LeetCode」2022年1月16日

本文最后更新于:2023年3月19日 晚上

  1. 链表随机节点

382. 链表随机节点

给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点** 被选中的概率一样** 。
实现 Solution 类:

  • Solution(ListNode head) 使用整数数组初始化对象。
  • int getRandom() 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等。

image.png

示例:
输入 [“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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
*/
var Solution = function (head) {
this.head = head;
};

/**
* @return {number}
*/
Solution.prototype.getRandom = function () {
let target;
let res = this.head;
let count = 0;
while (res) {
const random = Math.random();
if (random < 1 / ++count) target = res;
res = res.next;
}
return target.val;
};

/**
* Your Solution object will be instantiated and called as such:
* var obj = new Solution(head)
* var param_1 = obj.getRandom()
*/