leetcode382. 链表随机节点(蓄水池采样算法)

给定一个单链表,随机选择链表的一个节点,并返回相应的节点值。保证每个节点被选的概率一样。

进阶:
如果链表十分大且长度未知,如何解决这个问题?你能否使用常数级空间复杂度实现?

示例:
// 初始化一个单链表 [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();

蓄水池采样算法
在未知总数的情况下,进行随机抽样。
思路,保证在前K位时,每位被选中的概率是一样的,都是1/K,在插入第K+1位时,每一位被选中的概率都是1/(1+K)。我们要做2件事,第一件事,让第K+1位被选中的概率变为1/(1+K),让前面K位被选中的概率有1/K,减少为1/(1+K)。
此时就是核心操作了,随机一个随机数(random(1+K)),有1/(1+K)的概率,使用新数替换被选中的数值,自然就有(K/(1+k))的概率不被选中,自然,每个数字被选中的概率又都一样了。
举个例子,第八位数字在总共十个数字中被选中的概率:
如果第八位被选中,那就是第八次被选中,且第九次和第十次没有被替换,概率分别是1/8、8/9、9/10。相乘之后就是1/10。

回到这道题,那就是典型的蓄水池采样问题,在不确定之后还有没有数字的情况下,保证之前的都是概率相等的
代码:

class Solution {

ListNode node = null;

public Solution(ListNode head) {
    node = head;
}

/**
 * Returns a random node's value.
 */
public int getRandom() {
    ListNode node = this.node;
    int point = 1;
    int value = 0;
    Random random = new Random();
    while (node != null) {
        if (random.nextInt(point) == 0) {
            value = node.val;
        }
        node = node.next;
        point++;
    }
    return value;
}

}

发布了127 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_33321609/article/details/103408173
今日推荐