[알고리즘] 조합(Combination)

[알고리즘] 조합(Combination)

Tags
Algorithm

조합

순열은 STL에 구현되어있는 next_permutation을 사용하면 되지만, 조합은 STL에 따로 구현된 함수가 없어서 따로 구현해야 한다. 조합의 구현은 next_permutation을 활용한 방법과 재귀를 활용한 방법 두가지가 있다.

1. next_permutation을 활용한 조합 생성

방법 설명

  • 주어진 배열을 정렬한 후, 특정 개수만큼의 10으로 비트마스크를 만든 다음, 이 마스크를 통해 가능한 모든 조합을 생성하는 방식입니다.
  • 예를 들어, 5C3 조합을 구하려면 [0, 0, 0, 1, 1]과 같은 배열을 만들고, next_permutation을 통해 배열의 모든 순열을 탐색합니다. 이때 1이 위치한 인덱스의 요소들을 조합으로 선택합니다.

구현 예시

#include <iostream> #include <vector> #include <algorithm> #include <numeric> using namespace std; int main() { vector<int> arr = { 1, 2, 3, 4, 5 }; //5C3 vector<int> bin = { 0, 0, 0, 1, 1 }; do { int index = 0; for (auto i : bin) { if (i == 0) { cout << arr[index] << ' '; } index++; } cout << "\n"; } while (next_permutation(bin.begin(), bin.end())); return 0; }

2. 재귀를 사용한 조합 생성

방법 설명

  • 조합을 생성할 때마다 직접적으로 배열에서 필요한 요소만 선택해 나가는 방식입니다.
  • 현재 위치에서 다음 요소를 선택할지 말지를 결정하면서 모든 조합을 탐색합니다.

구현 예시

void Collaboration(vector<int>& target, vector<int>& selected, int depth, int next, int r) { if (depth == r) { PrintArray(selected); return; } for (int i = next; i < target.size(); ++i) { selected.push_back(target[i]); Collaboration(target, selected, depth + 1, i + 1, r); selected.pop_back(); } }

next_permutation
recurtion
장점
구현이 간단함 모든 조합을 사전식으로 구할 수 있음 특정 순서대로 탐색할 수 있음
필요한 최소한의 연산만 수행 메모리 사용량과 연산량이 비교적 적음 요소의 수가 크거나 조합의 크기가 작을 때 효율적
단점
배열이 길면 비트마스크 크기가 커지고 불필요한 연산이 많아짐 순열을 매번 생성해야 하므로, 불필요한 계산이 발생
어려울 수 있고, 구현이 비교적 복잡함 조합의 순서를 정렬하지 않으면, 순서가 보장되지 않을 수 있습니다.