蓄水池算法--(java)

蓄水池算法

  • 蓄水池算法
    • 什么是蓄水池算法
    • 代码演示
  • bfprt算法

蓄水池算法

假设有一个源源吐出不同球的机器, 只有装下10个球的袋子,每一个吐出的球,要么放入袋子,要么永远扔掉 如何做到机器吐出每一个球之后,所有吐出的球都等概率被放进袋子里

什么是蓄水池算法

蓄水池算法(Reservoir Sampling Algorithm)是一种随机算法,用于从未知数量的数据流中随机选择 k 个元素,其中 k 为预设的正整数。该算法的主要思想是在不知道数据流长度的情况下,通过随机选择 k 个元素并将其标记为“蓄水池”,然后从第 k+1 个元素开始,每个元素被选中的概率与之前未被选中的元素数量成比例。

以下是蓄水池算法的详细步骤:

  1. 初始化:将前 k 个元素标记为“蓄水池”,并将其余元素标记为未选中
  2. 从第 k+1 个元素开始遍历数据流:对于每个新元素,以 k/n 的概率将其标记为“蓄水池”(其中 n 是数据流中元素的总数)。如果元素被标记为“蓄水池”,则将其加入蓄水池中,并从数据流中移除。如果元素未被标记为“蓄水池”,则将其保留在数据流中。
  3. 重复步骤 2 直到数据流中的所有元素都被处理

在完成蓄水池算法后,我们可以得到一个大小为 k 的随机样本,其中每个元素被选中的概率相等。由于算法是随机的,因此无法保证样本的准确性,但可以证明,当数据流中的元素数量足够大时,样本的准确性接近于 1。

蓄水池算法的时间复杂度为 O(mn),其中 m 是数据流中的元素数量,n 是每个元素的复杂度,因为需要对每个元素进行标记和移除操作。

代码演示

public static class RandomBox{
        private int[] bag;
        private int N;
        private int count;

        /**
         * 初始化
         * @param capacity
         */
        public RandomBox(int capacity){
            bag = new int[capacity];
            N = capacity;
            count = 0;
        }

        /**
         * 返回[1 , max] 上任何一个随机数
         */
        public int rand(int max){
            return (int)(Math.random() * max) + 1;
        }

        /**
         * 加入的规则
         * @param num
         */
        public void add(int num){
            count++;
            //袋子没有满时,直接放进去.
            if (count <= N){
                bag[count - 1] = num;
            }else {
                //    (N / count) 的概率放进袋子中 
                if (rand(count) <= N){
                    //袋子中(1 / N) 的概率选中一个 仍出去
                    bag[rand(N) - 1] = num;
                }
            }

        }
    }

bfprt算法

bfprt算法-查找无序数组中第k小的数字

你可能感兴趣的:(数据结构,算法,java,算法,java,开发语言,数据结构,leetcode)