LeetCode:382 Linked List Random Node蓄水池抽样算法
来源:互联网 发布:网络用语菜鸟什么意思 编辑:程序博客网 时间:2024/06/05 03:44
问题定义
长度为N的链表,N很大,但是不知道具体有多大。从N个元素中随机取出K个元素,只能遍历一次链表。用到的算法保证取出的元素恰好有K个,且他们是完全随机的(出现概率均相等)。
求解
该算法是针对从一个序列中随机抽取不重复的K个数,保证每个数被抽取到的概率为k/n这个问题而构建的。做法是:
首先构建一个可放K个元素的蓄水池,将序列的前K个元素放入蓄水池中。然后从第K+1个元素开始,以K/n的概率来决定该元素是否被替换到池子中,当遍历完所有元素之后,就可以得到随机挑选出的K个元素。复杂度为O(n)
其伪代码如下:
Init : a reservor(蓄水池) with the size:K
for i = k+1 to N
M = random(1,i);
if(M < K)
SWAP the Mth value and ith value
end for
证明
1.对于第i个数(i <K,在前K步被选中的概率是1,从第一步开始,i不被选中的概率为K/K+1,那么读到第n个数时,第i个数(i < k)被选中的概率 = 被选中的概率* 以后每一步不被换走的概率,即:1 * K/K+1 * k+1/K+2 *……*n-1/n = K/n
2.对于第j个数(j>=K)被选中的概率为:在他出现时被选中的概率 * 在他出现以后不被换走的概率,即:
K/j * j/j+1 *……* n-1/n = K/n
3.综上得证
题目
Given a singly linked list, return a random node’s value from the linked list. Each node must have the same probability of being chosen. Follow up: What if the linked list is extremely large and its length is unknown to you? Could you solve this efficiently without using extra space?
实现:
import java.util.Random; public class Solution {
private Random mRandom;
private ListNode head;
public Solution(ListNode head) {
this.head=head;
} /** *蓄水池抽样算法 */
public int getRandom() {
mRandom=new Random();
int pos = 1;
ListNode node = head;
ListNode res = head;
while(node != null) {
//一直取最末尾的一个数
if (mRandom.nextInt(pos) == (pos-1)) {
res = node;//此处不可直接return。取第一个值的时候概率是百分之百,直接返回。
}
pos = pos+1;
node = node.next;
}
return res == null ? head.val : res.val;
} /** *先获取长度再取随机值的方法 */
public int getRandomXX() {
int randomVaule = mRandom.nextInt(this.getLength());
int pos = 0; ListNode res = head;
while(res != null) {
if(pos == randomVaule) {
return res.val;
}
res = res.next;
pos++;
}
return res.val;
}
public int getLength() { int len = 0; ListNode node = head; while(node != null) {
len++; node = node.next;
}
return len;
}
}
0 0
- LeetCode:382 Linked List Random Node蓄水池抽样算法
- Leetcode Linked List Random Node C++(蓄水池抽样算法)
- 蓄水池抽样算法 LeetCode382. Linked List Random Node
- LeetCode:382. Linked List Random Node(蓄水池抽样算法C++)
- LeetCode 382 Linked List Random Node (蓄水池算法 推荐)
- 382.[LeetCode]Linked List Random Node(蓄水池算法)
- leetcode 382. Linked List Random Node 蓄水池算法
- 382. Linked List Random Node (蓄水池抽样,java)
- 382. Linked List Random Node 蓄水池抽样法
- 蓄水池算法382. Linked List Random Node
- Leetcode 382. Linked List Random Node 以及 水塘抽样算法
- LeetCode:382 Linked List Random Node
- LeetCode #382: Linked List Random Node
- leetcode 382 Linked List Random Node C++
- LeetCode[382] Linked List Random Node
- [leetcode][382] Linked List Random Node
- LeetCode 382 Linked List Random Node
- 【Leetcode】Linked List Random Node
- Linux 设备驱动之字符设备(二)
- 人工智能各种技术与算法
- 第十三周 【项目五 验证拓扑排序】
- Linux下编译安装apache
- 在填报表中如何正确使用自动增长的字段
- LeetCode:382 Linked List Random Node蓄水池抽样算法
- 怎么修改input中placeholder的字体颜色
- Android中SQLite数据库使用
- 润乾报表在OC4J服务器下的部署方法
- Android之RecyclerView
- mysql批量select插入
- java 用poi 将远程共享文件夹中word转html
- EventBus3.0.0的使用
- Linux 设备驱动之字符设备(三)