ライブラリ
Combination

Combination

キーワード

  • Combination

概要

配列から rr 個を選んで, 長さ rr の配列を返す.

計算量

O(nCr)=O(n!r!(nr)!)\mathrm{O}({}_n C_r) = \mathrm{O}(\frac{n!}{r!(n-r)!})

応用例

  • グラフの全探索

実装

go:

func Combinations[T any](iterable []T, r int) [][]T {
	n := len(iterable)
 
	if n < r {
		return [][]T{}
	}
 
	var result [][]T
	indices := make([]int, r)
	for i := 0; i < r; i++ {
		indices[i] = i
	}
 
	for {
		currentCombination := make([]T, r)
		for i, idx := range indices {
			currentCombination[i] = iterable[idx]
		}
		result = append(result, currentCombination)
 
		var i int
		for i = r - 1; i >= 0; i-- {
			if indices[i] != n-(r-i) {
				break
			}
		}
 
		if i == -1 {
			break
		}
 
		indices[i]++
		for j := i + 1; j < r; j++ {
			indices[j] = indices[j-1] + 1
		}
	}
 
	return result
}

TS:

function* combinations<T>(iterable: Iterable<T>, r: number) {
  const pool = [...iterable];
  const n = pool.length;
  if (n < r) return;
 
  const indices = [...new Array(r)].map((_, i) => i);
  yield indices.map((i) => pool[i]);
  while (true) {
    let i;
    for (i = r - 1; i >= 0; i--) {
      if (indices[i] !== n - (r - i)) {
        break;
      }
    }
    if (i === -1) return;
    indices[i]++;
    for (let j = i + 1; j < r; j++) {
      indices[j] = indices[j - 1] + 1;
    }
    yield indices.map((i) => pool[i]);
  }
}

ベンチマーク

go で行うと以下のようになった.

nrnCrns/op
10525210891
20638,7602734329
2871,184,04094758698

例題

引用