[程序员代码面试指南]第9章-蓄水池算法

题目描述

  • 从N个元素中随机抽取k个元素,但的k个数无法事先确定。
  • 在实际应用中,往往会遇到很大数据流的情况。因此,我们无法先保存整个数据流然后再从中选取,而是期望有一种将数据流遍历一遍就得到所选取的元素,并且保证得到的元素是随机的算法。
  • 特别地,此题元素为1-N。

解题思路

  • 蓄水池算法。

    1. 先选取个元素中的前k个元素,保存在集合中;
    2. 从第i(i>k)个元素开始,每次先以k/i概率选择是否让第i个元素留下。若第i个元素存活,则从集合中k个元素随机扔掉一个,并将该元素放入集合;否则直接扔掉该元素;
    3. 重复1或2,直到结束。最后集合中剩下的就是保证随机抽取的k个元素。
  • 证明:此种方法保证在选第N号球时,从i号球被选中到第N号球的过程中,第i号球最终留在袋子的概率是(k/i)(i/i+1)(i+1/i+2)....(N-1)/N=k/N

代码

public class Main {
    public static void main(String args[]) {
        int k=5,N=1000;
        int[] arr=new int[k];
        arr=getKNumsRandom(k,N);
        for(int i=0;i<k;++i) {
            System.out.println(arr[i]);
        }
    }

    public static int[] getKNumsRandom(int k,int N) {
        int arr[]=new int[k];
        for(int i=0;i<k;++i) {
            int num=i+1;
            arr[i]=num;
        }
        for(int i=k;i<N;++i) {
            int num=i+1;//
            if(rand(num)<=k) {//替换
                arr[rand(k)-1]=num;
            }
        }
        return arr;
    }

    public static int rand(int max) {
        int test=(int)(Math.random()*max)+1;
        return (int)(Math.random()*max)+1;//随机返回[1,max]的一个值
    }
}

原文地址:https://www.cnblogs.com/coding-gaga/p/10887347.html

时间: 2024-08-02 06:09:34

[程序员代码面试指南]第9章-蓄水池算法的相关文章

程序员代码面试指南 IT名企算法与数据结构题目最优解 ,左程云著pdf高清版免费下载

下载地址:网盘下载 备用地址:网盘下载 内容简介  · · · · · ·这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮助广大程序员的面试准备做到万无一失.“刷”完本书后,你就是“题王”!__eol__本书采用题目+解答的方式组织内容,并把面试题类型相近或者解法相近的题目尽量放在一起,读者在学习本书时很容易看出面试题解法之间的联系,使知识的学习避免碎片化

《程序员代码面试指南》第八章 数组和矩阵问题 将正方形矩阵顺时针转动90

题目 将正方形矩阵顺时针转动90 java代码 package com.lizhouwei.chapter8; /** * @Description: 将正方形矩阵顺时针转动90 * @Author: lizhouwei * @CreateDate: 2018/4/28 22:16 * @Modify by: * @ModifyDate: */ public class Chapter8_2 { public void rotate(int[][] matrix) { int tR = 0; i

《程序员代码面试指南》第八章 数组和矩阵问题 需要排序的最短子数组长度

题目 需要排序的最短子数组长度 java代码 package com.lizhouwei.chapter8; /** * @Description: 需要排序的最短子数组长度 * @Author: lizhouwei * @CreateDate: 2018/4/29 8:03 * @Modify by: * @ModifyDate: */ public class Chapter8_5 { public int getMinLength(int[] arr) { if (arr == null

《程序员代码面试指南》第八章 数组和矩阵问题 &quot;之&quot;字形打印矩阵

题目 "之"字形打印矩阵 java代码 package com.lizhouwei.chapter8; /** * @Description: "之"字形打印矩阵 * @Author: lizhouwei * @CreateDate: 2018/4/28 22:53 * @Modify by: * @ModifyDate: */ public class Chapter8_3 { public void printMatrixZigZag(int[][] matri

《程序员代码面试指南》第八章 数组和矩阵问题 自然数数组的排序

题目 自然数数组的排序 java代码 package com.lizhouwei.chapter8; /** * @Description: 自然数数组的排序 * @Author: lizhouwei * @CreateDate: 2018/5/8 20:51 * @Modify by: * @ModifyDate: */ public class Chapter8_14 { public void sort(int[] arr) { int left = 0; int right = arr.

《程序员代码面试指南》第八章 数组和矩阵问题 不包含本位置值的累乘数组

题目 不包含本位置值的累乘数组 java代码 package com.lizhouwei.chapter8; /** * @Description: 不包含本位置值的累乘数组 * @Author: lizhouwei * @CreateDate: 2018/5/9 21:11 * @Modify by: * @ModifyDate: */ public class Chapter8_22 { public int[] product(int[] arr) { int[] res = new in

[程序员代码面试指南]数组和矩阵问题-找到无序数组中最小的k个数(堆排序)

题目链接 https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&tqId=11182&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking 题目描述 从无序序列,找到最小topk个元素. 解题思路 使用大根堆维护最小topk个元素: - 首先前k个元素建立大根堆(从

[程序员代码面试指南]数组和矩阵问题-未排序正数数组中累加和为给定值的最长子数组长度

题目描述 给定无序数组,每个值均为正数,再给定整数k.求arr中所有子数组中所有元素相加和为k的最长子数组长度.无则输出-1. 例: 输入 arr=[1,2,1,1,1],k=3 输出 3 解题思路 (时间复杂度O(N),空间复杂度O(1)) 维护指针l,r表示子数组区间.初始l=r=0,向右移动至r=arr.length结束. 维护当前子数组和sum,及到当前为止满足题意的最大len.初始sum=arr[0],len=-1. 每次比较sum和k,根据情况选择移动l还是r,并更新sum和len.

[程序员代码面试指南]递归和动态规划-机器人达到指定位置方法数(一维DP待做)

题目描述 一行N个位置1到N,机器人初始位置M,机器人可以往左/右走(只能在位置范围内),规定机器人必须走K步,最终到位置P.输入这四个参数,输出机器人可以走的方法数. 解题思路 DP 方法一:时间复杂度O(NK),空间复杂度O(NK) 方法二:时间复杂度O(NK),空间复杂度O(N) 方法一代码 //ans=walk(N,M,K,P); public static int walk(int N,int cur,int rest,int P) { int[][] dp=new int[rest+