Cómo escribir un algoritmo que tome una muestra aleatoria de tamaño k de una secuencia de n elementos

Lo que estás buscando se llama muestreo de yacimientos.

El algoritmo estándar para el muestreo de yacimientos es el Algoritmo R, que requiere espacio [matemático] \ Theta (k) [/ matemático]. Con el Algoritmo R , cada muestra es igualmente probable que se seleccione, y no es necesario conocer el tamaño de [math] n [/ math] con anticipación.

Aquí hay un código Java para ello:

 import java.util.Arrays;  import java.util.Iterator;  import java.util.Random;  public class ReservoirSampling {private static Random randomNumberGenerator = new Random ();  public static void main (String [] args) arroja IllegalArgumentException {Iterable  values ​​= Arrays.asList (new Integer [] {4, 9, 3, 1, 30, 32, 35, 41, 38, 2, 39, 30, 45, 76, 21, 2});  int sampleSize = 5;  int [] randomSample = getRandomSample (valores, sampleSize);  System.out.println ("Muestra aleatoria:" + Arrays.toString (randomSample));  } public static int [] getRandomSample (Iterable  values, int sampleSize) arroja IllegalArgumentException {if (values ​​== null) {throw new IllegalArgumentException ("Debe proporcionar valores de los cuales tomar muestras");  } int [] randomSample = new int [sampleSize];  Iterador  valueIterator = values.iterator ();  for (int sampleIndex = 0; valueIterator.hasNext (); ++ sampleIndex) {Valor entero = valueIterator.next ();  if (sampleIndex <sampleSize) {randomSample [sampleIndex] = value;  } else {int randomNumber = getRandomIntegerInRange (0, sampleIndex);  if (randomNumber <sampleSize) {randomSample [randomNumber] = value;  }}} return randomSample;  } private static int getRandomIntegerInRange (int min, int max) {return min + randomNumberGenerator.nextInt ((max - min) + 1);  }}