Reservoir Sampling & Quickselect

本文介绍了两种高效的数据处理算法:Reservoir Sampling 和 Quickselect。Reservoir Sampling 用于从大量数据中随机抽取样本,尤其适合内存限制场景。Quickselect 则是一种线性时间复杂度的选择算法,能够快速找到未排序数组中的第 k 小元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Reservoir Sampling

适用于从很大的数据堆里随机取样,一般适用于内存不足以装入所有数据的情况。


从n个数据里随机取k个数

1. 用前k个数据组成一个reservoir

2. 从k+1开始,对于第i个元素,随机产生一个1~i之间的数j,如果j<=k,则reservoir里第j个元素就被i替换掉。直到n个数据都被试过。


证明tips

每次循环,reservoir里第j个(j<=k)元素被替换的概率是1/k * k/i = 1/i


Quickselect

O(n),每次都去掉一半剩余单边

package leetcode.blog;

public class Quickselect {
	public static int partition(int[] array, int left, int right, int pivotIndex){
		int pivot = array[pivotIndex];
		swap(array, right, pivotIndex);
		int start = left;
		for(int i = left; i < right; i++){
			if(array[i] <= pivot){
				swap(array, start, i);
				start++;
			}
		}
		swap(array, start, right);
		return start;
	}
	
	public static void swap(int[] array, int source, int sink){
		int temp = array[sink];
		array[sink] = array[source];
		array[source] = temp;
	}
	
	public static int select(int[] array, int left, int right, int k){
		if(left == right)
			return array[left];
		int pivotIndex = left + (int)Math.floor(Math.random() * (right - left + 1));
		pivotIndex = partition(array, left, right, pivotIndex);
		if(k == pivotIndex)
			return array[pivotIndex];
		else if (k < pivotIndex - 1)
			return select(array, left, pivotIndex - 1, k);
		else
			return select(array, pivotIndex + 1, right, k);
	}
	
	public static void main(String[] args){
		int[] array = new int[]{4, 5, 8, 1, 3, 2, 0, 6, 7, 10, 9};
		System.out.println(select(array, 0, 10, 3));
		System.out.println(select(array, 0, 10, 6));
		System.out.println(select(array, 0, 10, 7));
		System.out.println(select(array, 0, 10, 8));
		System.out.println(select(array, 0, 10, 9));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值