• 蓄水池抽样算法 Reservoir Sampling


    2018-03-05 14:06:40

    问题描述:给出一个数据流,这个数据流的长度很大或者未知。并且对该数据流中数据只能访问一次。请写出一个随机选择算法,使得数据流中所有数据被选中的概率相等。

    问题求解:如果是长度已知或者有限的问题,那么可以使用朴素的方法,先遍历一遍得到的长度。然后在得到长度后可以使用随机算法得到一个随机的index。

    但是本题已经明确指出数据流长度很大或者未知,也就是说只能遍历一次,而且要保证每个数被挑选的概率相等。

    标准解法是使用Reservoir Sampling算法,该算法由Knuth的学生在斯坦福读计算机博士时想出来

    算法描述:

    相关问题:

    • 382. Linked List Random Node

    问题描述

    问题求解:

    public class Solution {
        ListNode head;
        Random rand;
    
        /** @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.head = head;
            this.rand = new Random();
        }
    
        /** Returns a random node's value. */
        public int getRandom() {
            int k = 1;
            ListNode cur = head;
            List<Integer> reservoir = new ArrayList<>();
            int i = 0;
            while (i < k && cur != null) {
                reservoir.add(cur.val);
                cur = cur.next;
                i++;
            }
            i++;
            while (cur != null) {
                if (rand.nextInt(i) < k) {
                    reservoir.set(rand.nextInt(k), cur.val);
                }
                i++;
                cur = cur.next;
            }
            return reservoir.get(0);
        }
    }
    
    • 398. Random Pick Index

    问题描述:

    问题求解:

    如果仅存在一个数,那么将之index返回,如果存在多个数,其index的返回值需要是等概率的,也就是说对于k个相同的数,我们需要每个index的返回概率为1/k。根据蓄水池算法,我们首先要建立一个大小为1的池子,然后对每个出现的target的index以当前出现个数的概率选择他,然后从池中随机挑选一个数来与它交换,由于池中仅有一个值,因此只需要将res的值变为挑选值即可。

    public class RandomPickIndex {
        int[] nums;
        Random ran;
    
        public RandomPickIndex(int[] nums) {
            this.nums = nums;
            ran = new Random();
        }
    
        public int pick(int target) {
            int res = -1;
            int cnt = 0;
            for (int i = 0; i < nums.length; i++) {
                if (nums[i] != target) continue;
                if (ran.nextInt(++cnt) == 0) res = i;
            }
            return res;
        }
    }
    
  • 相关阅读:
    实习第五十七天
    武汉第五十六天
    武汉第五十五天
    常用环境配置
    http 基本验证(nginx)
    nginx configuration
    docker run demo
    初识Hadoop
    大数据简介
    HDFS 存放策略
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/8508759.html
Copyright © 2020-2023  润新知