leetcode 382. 链表随机节点

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

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

进阶:
如果链表非常大且长度未知,该怎么处理?
你能否在不使用额外空间的情况下解决此问题?

方法1 [空间复杂度O(n)]

我们可以在初始化时,用一个数组记录链表中的所有元素,这样随机选择链表的一个节点,就变成在数组中随机选择一个元素。使用rand()方法即可。

方法2 [空间复杂度O(1)]

使用蓄水池抽样算法:
假设有数据流 1, 2, 3, ..., n。
怎么在不知道n的具体值得情况下使得其中某个值m被抽样的概率为1/n呢?

规定当遍历到m时我们以1/m的概率取得m,那么最终结果为m的要求是:m+1, m+2, ... , n都不会被抽到,这些概率为m/m+1,m+1/m+2, ..., n-1/n。
综上,最终抽取得值为m的概率为1/m × m/m+1 × m+1/m+2 × ... × n-1/n = 1/n。与m前面的值是否被抽样,因为m抽到会覆盖

优点:蓄水池抽样由于空间小,可以用于大数据流中的随机抽样问题。

代码

class Solution {
public:
    ListNode* h;
    Solution(ListNode* head) {
        h = head;
    }
    
    int getRandom() {
        int ans = 0, n = 1;
        for (ListNode* p = h; p; p = p->next, n++) {
            if (rand() % n == 0) ans = p->val;
        }
        return ans;
    }
};

zahlenw2
1 声望0 粉丝

引用和评论

0 条评论