SorryToPerson logo
返回
算法2026-04-19·6 分钟

算法知识库:随机化算法实现

JavaScript/TypeScript 实现随机化算法,如随机洗牌、随机采样、蒙特卡洛方法等。

随机化算法实现

1. Fisher-Yates 洗牌算法

ts
function shuffle<T>(array: T[]): T[] {
  const shuffled = [...array];
  for (let i = shuffled.length - 1; i > 0; i -= 1) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
  }
  return shuffled;
}

2. 随机采样 (水库采样)

ts
function reservoirSampling<T>(stream: T[], k: number): T[] {
  const reservoir: T[] = [];

  // 填充前 k 个元素
  for (let i = 0; i < k && i < stream.length; i += 1) {
    reservoir.push(stream[i]);
  }

  // 对剩余元素进行随机替换
  for (let i = k; i < stream.length; i += 1) {
    const j = Math.floor(Math.random() * (i + 1));
    if (j < k) {
      reservoir[j] = stream[i];
    }
  }

  return reservoir;
}

3. 快速选择算法 (随机化版本)

ts
function quickSelect<T>(arr: T[], k: number, compare: (a: T, b: T) => number): T {
  if (arr.length === 1) return arr[0];

  const pivotIndex = Math.floor(Math.random() * arr.length);
  const pivot = arr[pivotIndex];

  const left: T[] = [];
  const right: T[] = [];
  const equal: T[] = [];

  for (const item of arr) {
    const cmp = compare(item, pivot);
    if (cmp < 0) left.push(item);
    else if (cmp > 0) right.push(item);
    else equal.push(item);
  }

  if (k < left.length) {
    return quickSelect(left, k, compare);
  } else if (k < left.length + equal.length) {
    return pivot;
  } else {
    return quickSelect(right, k - left.length - equal.length, compare);
  }
}

4. 蒙特卡洛 π 值估算

ts
function estimatePi(numPoints: number): number {
  let insideCircle = 0;

  for (let i = 0; i < numPoints; i += 1) {
    const x = Math.random();
    const y = Math.random();

    if (x * x + y * y <= 1) {
      insideCircle += 1;
    }
  }

  return (insideCircle / numPoints) * 4;
}

5. 随机化快速排序

ts
function randomizedQuickSort<T>(arr: T[], compare: (a: T, b: T) => number): T[] {
  if (arr.length <= 1) return arr;

  const pivotIndex = Math.floor(Math.random() * arr.length);
  const pivot = arr[pivotIndex];

  const left: T[] = [];
  const right: T[] = [];

  for (let i = 0; i < arr.length; i += 1) {
    if (i === pivotIndex) continue;
    if (compare(arr[i], pivot) <= 0) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }

  return [...randomizedQuickSort(left, compare), pivot, ...randomizedQuickSort(right, compare)];
}

6. 随机数生成器

ts
class Random {
  private seed: number;

  constructor(seed?: number) {
    this.seed = seed ?? Math.floor(Math.random() * 1000000);
  }

  next(): number {
    this.seed = (this.seed * 9301 + 49297) % 233280;
    return this.seed / 233280;
  }

  nextInt(min: number, max: number): number {
    return Math.floor(this.next() * (max - min + 1)) + min;
  }
}

7. 实现要点

  • Fisher-Yates 保证均匀分布。
  • 水库采样处理大数据流。
  • 随机化枢轴避免最坏情况。
  • 蒙特卡洛方法通过概率收敛。
算法随机化JavaScript