본문으로 건너뛰기
김신건의 로그

Randomization (무작위화)

· 수정 · 📖 약 3분 · 1,122자/단어 #algorithm #math #probability #randomization
randomization, randomized algorithm, 무작위 알고리즘, Las Vegas, Monte Carlo, Fisher-Yates, random shuffle

정의

무작위화 (Randomization) 는 알고리즘 내부에 난수를 도입하여 평균 성능 향상 또는 결정론적 방법보다 단순한 해결책 을 얻는 기법. 크게 두 부류로 나뉜다:

  • Las Vegas: 항상 정답을 반환하지만 실행 시간이 확률적 (예: Randomized Quicksort, Fisher-Yates Shuffle)
  • Monte Carlo: 실행 시간은 일정하지만 확률적으로 오답 가능 (예: Miller-Rabin 소수 판정, Freivalds 행렬 검증)

문제 상황과 동기

결정론적 알고리즘이 최악의 경우 느리거나 복잡할 때 무작위성이 강력한 도구가 됨.

  • Quicksort: 결정론적 pivot 선택은 O(N^2) 최악. 무작위 pivot 은 O(N log N) expected.
  • 소수 판정: 결정론적 AKS 는 O(log^6 N). Miller-Rabin 은 O(k log^3 N) with k 반복.
  • Shuffling: 정렬 기반 셔플은 중복 편향. Fisher-Yates 는 균일한 순열 보장.
  • Load Balancing: 해시 테이블, Consistent Hashing.

핵심 통찰: 난수로 입력의 최악의 경우를 회피하거나, 높은 확률로 정답을 보장.

시각화

핵심 아이디어

Las Vegas 알고리즘

1. 항상 올바른 결과 반환
2. 런타임이 확률 변수
3. 기대 시간 분석 (Expected Time)

예: Randomized Quicksort
  pivot 을 무작위로 선택
  최악 입력에도 expected O(N log N)

Monte Carlo 알고리즘

1. 고정된 시간에 실행
2. 높은 확률로 정답 (1 - ε)
3. 반복 실행으로 오류 확률 지수 감소

예: Miller-Rabin
  k 번 반복하면 합성수를 소수로 오판할 확률 4^(-k)

Seeding

난수 생성기의 초기값을 고정하면:
- 디버깅 가능 (재현성)
- 대회 환경에서 결과 일관성
- mt19937 rng(seed) 또는 uniform_int_distribution

알고리즘

Fisher-Yates Shuffle (Knuth Shuffle):
    for i = N-1 down to 1:
        j = random(0, i)    // 0 <= j <= i
        swap(a[i], a[j])
    # 모든 N! 순열이 동일 확률

Monte Carlo Pi Estimation:
    inside = 0
    for i = 1 to N:
        x, y = uniform(0, 1)
        if x² + y² <= 1: inside++
    pi ≈ 4 * inside / N

Randomized Quickselect:
    pivot = random element
    partition around pivot
    recurse on appropriate side
    expected O(N)

구현

// Fisher-Yates Shuffle + Monte Carlo Pi estimation
// Fixed seed for reproducibility
#include <bits/stdc++.h>
using namespace std;

// Simple LCG for cross-platform determinism
int rng_state;
int lcg_rand(int n) {
  rng_state = (rng_state * 1103515245LL + 12345) & 0x7fffffff;
  return rng_state % n;
}

int main() {
  int mode; cin >> mode;
  rng_state = 42;

  if (mode == 0) {
      // Fisher-Yates shuffle
      int n; cin >> n;
      vector<int> a(n);
      for (int i = 0; i < n; i++) a[i] = i + 1;
      for (int i = n - 1; i > 0; i--) {
          int j = lcg_rand(i + 1);
          swap(a[i], a[j]);
      }
      for (int x : a) cout << x << " ";
      cout << "\n";
  } else {
      // Monte Carlo Pi
      int trials; cin >> trials;
      int inside = 0;
      for (int i = 0; i < trials; i++) {
          int x = lcg_rand(1000001);
          int y = lcg_rand(1000001);
          if ((long long)x * x + (long long)y * y
              <= (long long)1000000 * 1000000)
              inside++;
      }
      double pi = 4.0 * inside / trials;
      cout << fixed << setprecision(6);
      cout << pi << "\n";
  }
}
stdin
0
6
결과
3 5 1 6 2 4

복잡도

항목
Fisher-Yates ShuffleO(N) 시간, O(1) 공간 (in-place)
Monte Carlo PiO(N) 시간 (N trials), O(1) 공간
Miller-Rabin (k 반복)O(k log^3 N) 시간, O(1) 공간
Randomized QuickselectO(N) expected, O(N^2) worst

Las Vegas vs Monte Carlo 상세

속성Las VegasMonte Carlo
정답 보장항상높은 확률
시간확률적결정론적
오류 방향없음일방향 / 양방향
반복 효과시간 분산오류율 지수 감소
Randomized Quicksort, Fisher-Yates, TreapMiller-Rabin, Freivalds, MinHash

Las Vegas -> Monte Carlo 변환

Las Vegas 알고리즘을 시간 제한으로 중단하면 Monte Carlo 로 변환. 시간 제한 내 완료 못하면 “모름” 반환.

오류 확률 감소

Monte Carlo 알고리즘을 k 번 독립적으로 실행하고 다수결로 결과를 취하면 오류 확률이 지수적으로 감소. 1회 오류율이 p < 1/2 이면, k 회 후 오류율 ≤ exp(-2k(1/2 - p)^2) (Chernoff bound).

변형 / 활용

기법설명
Fisher-Yates Shuffle균일한 무작위 순열 생성, O(N)
Reservoir Sampling스트림에서 균일 샘플링, O(1) 공간
Randomized TreapBST + heap, 균형을 무작위성으로 보장
Bloom FilterMonte Carlo 집합 멤버십, 거짓 양성 가능
Locality-Sensitive Hashing근사 유사도 검색
MinHash집합 유사도 추정 (Jaccard)
Simulated Annealing무작위성으로 지역 최적 탈출

함정

1. seed 고정과 보안

암호학적 용도로 rand()mt19937 사용 금지. arc4random 또는 CSPRNG 사용. PS 에서는 mt19937 + fixed seed 로 충분.

2. Fisher-Yates 오구현

잘못된 예: for i in 0..N-1:
             j = random(0, N-1)   # N 전체!
             swap(a[i], a[j])

이 경우 편향된 순열이 생성됨. 올바른 범위는 random(0, i).

3. Monte Carlo 신뢰도

Miller-Rabin 에서 k=1 이면 합성수를 소수로 판정할 확률 1/4. k=10 이면 4^(-10) ≈ 10^(-6). 현장에서는 k=20 이상 권장.

4. 재현성

디버깅과 대회 환경을 위해 seed 고정 필수. 디버그 모드와 배포 모드에서 seed 전략 다르게.

5. modulo 편향

rand() % n 은 n 이 RAND_MAX 의 약수가 아닐 때 편향. C++ 의 uniform_int_distribution 사용.

BOJ 연습 문제

번호제목정답률링크
BOJ 1450냅색문제-kokoa-lab
BOJ 1208부분수열의 합 2-kokoa-lab
BOJ 7453합이 0인 네 정수-kokoa-lab
BOJ 2295세 수의 합-kokoa-lab

참고

이 글의 용어 (6개)
문자열 해싱 (String Hashing)algorithm
정의 문자열 해싱 (String Hashing) 은 문자열을 고정 길이의 정수 (해시값) 로 매핑하여, 부분 문자열 비교를 O(1) 에 수행할 수 있게 만드는 기법. Rabin과…
소수 판정 (Primality Test)algorithm
정의 소수 판정 (Primality Test) 은 주어진 정수 N이 소수인지 합성수인지 판별하는 알고리즘. 시행 나눗셈 (Trial Division) O(√N), 확률적 Ferm…
확률 (Probability)algorithm
정의 확률 (Probability) 은 사건이 발생할 가능성을 수치화한 값. 표본 공간 Ω 에 대해 P(A) = |A| / |Ω| (동일 확률), 또는 더 일반적으로는 σ-alg…
Birthday Problem (생일 문제)algorithm
정의 생일 문제 (Birthday Problem) 는 N 개의 동등한 가능성이 있는 결과에서 무작위로 k 개를 선택할 때 적어도 하나의 충돌이 발생할 확률을 분석하는 문제. 충돌…
Miller-Rabin 소수 판정 (Miller-Rabin Primality Test)algorithm
정의 Miller-Rabin 소수 판정 은 N 이 소수인지 확률적/결정론적으로 판별하는 알고리즘. Fermat 작은 정리와 이차잉여 성질을 결합해 O(k log^3 N) 에 동작…
Pollard Rho 소인수분해 (Pollard's Rho Algorithm)algorithm
정의 Pollard Rho 는 큰 정수 N 의 비자명 약수를 O(N^(1/4)) 확률적 시간에 찾는 알고리즘. 생일 역설 (Birthday Paradox) 을 활용해 난수 수열의…

이 개념을 다룬 위키 페이지 (1)

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기