美文网首页
leetcode382. Linked List Random

leetcode382. Linked List Random

作者: 今天不想掉头发 | 来源:发表于2019-08-06 12:11 被阅读0次

    这道题本质是到蓄水池算法


    image.png

    https://leetcode.com/problems/linked-list-random-node/discuss/85659/brief-explanation-for-reservoir-sampling
    https://zhuanlan.zhihu.com/p/29178293

    先说一下普遍的情况吧:
    要求对于一个流式数据,在不知道n的情况下,保证能够随机取出k个数。

    只要我们保证对于每一个新的数,都以k/(k+i)的概率取值,直到k+i = n为止即可。

    对于k = 1的情况:设一个额外的桶长度为1

    取第一个数的概率为1;

    取第二个数的概率为1/2,那么对于第一个数,依然留在桶里的概率为1 * 1/2(不取第二个数);

    取第三个数的概率为1/3,那么对于第一个数,依然留在桶里的概率为1 * 1/2 * (1 – 1/3)=1/3(原先的概率乘以不取第三个数的概率),对于第二个数,依然留在桶里的概率为1/2 * (1 – 1/3)=1/3(同理);

    取第四个数的概率为1/4,那么对于第一个数,1 * 1/2 * (1 – 1/3) * (1 – 1/4) = 1/4。第二个数,1/2 * (1 – 1/3) * (1 – 1/4) = 1/4。第三个数,1/3 * (1 – 1/4) = 1/4

    以此类推,直到n,n中每个数取到的概率都是1/n。

    对于k>1的情况:设桶长度为k

    取前k个数的概率都是1;

    取第k+1个数概率为k/(k + 1),对于第一个数,1/(k+1) (没有选中第k+1个数,1 - (k/k+1)) + k/(k + 1) * (k - 1)/k (选中了第k+1个数,但是替换的是其他的k-1个数,而非第一个数)。对于剩下的k-1个数同理;

    取第k+2个数概率为k/(k + 2),同上;

    以此类推,直到n,n中每个数取到的概率都是k/n。

    再看下本题的内容,要求以等概率的形式取得链表中的每个节点的值,所以我们只要保证,随着链表往后遍历,每次都是以1/i的概率取得当前节点的值就可以了

    class Solution {
        ListNode p;
        /** @param head The linked list's head.
            Note that the head is guaranteed to be not null, so it contains at least one node. */
        public Solution(ListNode head) {
            this.p = head;
        }
        
        /** Returns a random node's value. */
        public int getRandom() {
            Random random = new Random();
            ListNode cur = p;
            int res = cur.val;
            for (int i = 1; cur.next != null; i++) {
                cur = cur.next;
                if (random.nextInt(i + 1) == i) res = cur.val;
            }
            return res;
        }
    }
    

    相关文章

      网友评论

          本文标题:leetcode382. Linked List Random

          本文链接:https://www.haomeiwen.com/subject/awsidctx.html