题目:
解题思路:首先是要实现使用整数数组初始化对象,这里由于我们不知道每次输入的数组长度是多少因此我们可以定义一个链表类型的类的成员变量用链表来存储数据。第二步根据题意我们可以使用random.nextInt方法来随机生成一个[0,list.size())范围内的值,这样我们就可以直接实现随机选择节点并且保证每个节点被选择个概率相等的目的。
class Solution {
ListNode head = new ListNode();
ArrayList<ListNode> result = new ArrayList();
int num = 0;
public Solution(ListNode head) {
while(head!=null){
result.add(head);
head = head.next;
}
num = result.size();
}
public int getRandom() {
Random random = new Random();
int s = random.nextInt(num);
ListNode node = new ListNode();
return result.get(s).val;
}
}
补充:蓄水池算法
既然是随机获取一个节点那么从本质上来说这一过程就是一个采样的过程。当数据整体规模较小时我们可以直接使用随机数生成来获取K个样本的索引,但是如果当数据的规模巨大时仅仅将全部的数据遍历一遍就会造成一定的开销那么此时再遍历一遍获取样本总量N再用random.nextInt(N)的方法可能就不太合适了,这个时候我们就可以使用一种蓄水池算法来解决这一问题。
算法过程:
首先假设有n个样本,需要取样k个
我们可以维护一个大小为k的数组,当i<=k时我们直接将样本放入数组中
然后从第k+1个开始我们以k/n的概率来决定这个数据是否留在数组中,当完成遍历后我们最后得到的数组就是取样的样本。
证明:
当i<=k时每个数据都会被放入数组中,此时数据被选择的选择的概率为1,当i=k+1时,此时选中第k+1个数据的概率为k/(k+1),被踢出数据的元素为第i个的概率为1/k,因此第i个元素不被选中个概率为1- [k/(k+1) * 1/k] = k/(k+1)。
那么数据i在不被k+1个数据替换的前提下不备第k+2个元素替换的概率为1-[k/k+2 * 1/k] = k/k+2,以此类推,当到第n个数据时i仍旧不会被替换的概率为
1* k/k+1 *k+1/k+2 *…*n-1/n = k/n
本题目中获取一个数据因此直接令k=1。
class Solution {
ListNode head = new ListNode();
ArrayList<ListNode> result = new ArrayList();
int num = 0;
public Solution(ListNode head) {
while(head!=null){
result.add(head);
head = head.next;
}
num = result.size();
}
public int getRandom() {
int a = result.get(0).val;
Random random = new Random();
for(int i = 1;i<=result.size();i++){
if(random.nextInt(i)==0){
a = result.get(i-1).val;
}
}
return a;
}
}