给定一个单链表,随机选择链表的一个节点,并返回相应的节点值。保证每个节点被选的概率一样。
进阶:
如果链表十分大且长度未知,如何解决这个问题?你能否使用常数级空间复杂度实现?
示例:
// 初始化一个单链表 [1,2,3]. ListNode head = new ListNode(1); head.next = new ListNode(2); head.next.next = new ListNode(3); Solution solution = new Solution(head); // getRandom()方法应随机返回1,2,3中的一个,保证每个元素被返回的概率相等。 solution.getRandom();
蓄水池抽样问题。即从一个包含 n 个对象的列表 S 中随机选取 k 个对象,n 为一个非常大或者不知道的值。通常情况下,n 是一个非常大的值,大到无法一次性把所有列表 S 中的对象都放到内存中。我们这个问题是蓄水池抽样问题的一个特例,即 k=1。
解法:我们总是选择第一个对象,以 1/2 的概率选择第二个,以 1/3 的概率选择第三个,以此类推,以 1/m 的概率选择第 m 个对象。当该过程结束时,每一个对象具有相同的选中概率,即 1/n。
证明:第 m 个对象最终被选中的概率 P = 选择 m 的概率 × 其后面所有对象不被选择的概率
,即:
思路同:398. 随机数索引
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def __init__(self, head: Optional[ListNode]):
self.head = head
def getRandom(self) -> int:
n = ans = 0
head = self.head
while head:
n += 1
x = random.randint(1, n)
if n == x:
ans = head.val
head = head.next
return ans
# Your Solution object will be instantiated and called as such:
# obj = Solution(head)
# param_1 = obj.getRandom()
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
private ListNode head;
private Random random = new Random();
public Solution(ListNode head) {
this.head = head;
}
public int getRandom() {
int ans = 0, n = 0;
for (ListNode node = head; node != null; node = node.next) {
++n;
int x = 1 + random.nextInt(n);
if (n == x) {
ans = node.val;
}
}
return ans;
}
}
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(head);
* int param_1 = obj.getRandom();
*/
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* head;
Solution(ListNode* head) {
this->head = head;
}
int getRandom() {
int n = 0, ans = 0;
for (ListNode* node = head; node != nullptr; node = node->next)
{
n += 1;
int x = 1 + rand() % n;
if (n == x) ans = node->val;
}
return ans;
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(head);
* int param_1 = obj->getRandom();
*/
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
type Solution struct {
head *ListNode
}
func Constructor(head *ListNode) Solution {
return Solution{head}
}
func (this *Solution) GetRandom() int {
n, ans := 0, 0
for node := this.head; node != nil; node = node.Next {
n++
x := 1 + rand.Intn(n)
if n == x {
ans = node.Val
}
}
return ans
}
/**
* Your Solution object will be instantiated and called as such:
* obj := Constructor(head);
* param_1 := obj.GetRandom();
*/