【笔记】关于蓄水池算法的一个java题

一、题目如下:
给一个整数N和一个特别大内存装不下的纯文本文件,从这个文件随机抽N行文本返回

public List<String> extractLines(String filePath,int n){
//todo 在这里填充代码
}

要求:文件只读一遍,占用的内存最多只有N+1行;每行最多算一个随机数;返回的文本行顺序要跟原文件中的文本行顺序保持一致。
关键是“随机”
以下做法是错的:1.把整个文件一次读到内存再计算随机数;2.使用LineNumberReader;3.预先算n个随机数

二、蓄水池算法

蓄水池算法是针对从一个序列中随机抽取不重复的K个数,保证每个数被抽取到的概率都为K/N这个问题构建的
做法:
首先构造一个可以容纳k个元素的蓄水池,将序列前k个元素直接放入蓄水池中
然后从第k+1个数据开始,以k/i(k<i=n)的概率来决定它是否进入蓄水池。
当遍历完N个数据,蓄水池中所剩的K个元素就是就是挑选出的元素
时间复杂度为O(N)

三、java实现
public static List<String> extractLines(String filePath, int n) throws IOException {
        List<String> randomLines = new ArrayList<>();
        FileReader fr = new FileReader(filePath);
        BufferedReader br = new BufferedReader(fr);
        for (int j = 0; j < n; j++) {
            String line = br.readLine();
            randomLines.add(line);
        }
        for (int i = 0;; i++) {
            String readLine = br.readLine();
            if (StringUtils.isBlank(readLine)) {
                break;
            }
            Random random = new Random();
            int nextInt = random.nextInt(n + i) ;
            if (nextInt < n) {
                randomLines.remove(nextInt);
                randomLines.add(readLine);
            }
        }
        return randomLines;
    }
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值