[Algorithm] 순열과 조합, 중복 순열과 중복 순열 (DFS,경우의 수)

Posted by DHniyeo Blog on April 13, 2024

개요

코딩 문제를 보다 보면 DFS를 활용하는 문제에서 순열, 조합, 중복순열, 중복 조합이 등장한다. 그래서 한번 정리를 하게 되었다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <vector>
using namespace std;

int arr[5] = { 1,2,3,4,5 };
int visited[5] = {0};
vector<int> vc;
void printvc() {
	for (int i = 0; i < vc.size(); i++) {
		cout << vc[i] << " ";
	}
	cout << endl;
}
void dfs_permu(int depth) { // 순열 : visited[]있음
	if (depth == 3) {
		printvc();
		return;
	}
	for (int i = 0; i < 5; i++) {
		if (visited[i] == 1)continue;
		visited[i] = 1;
		vc.push_back(arr[i]);
		dfs_permu(depth + 1);
		vc.pop_back();
		visited[i] = 0;
	}

}
void dfs_combi(int depth,int idx) { // 조합 : visited[]있음, idx 변수 추가
	if (depth == 3) {
		printvc();
		return;
	}
	for (int i = idx; i < 5; i++) {
		if (visited[i] == 1)continue;
		visited[i] = 1;
		vc.push_back(arr[i]);
		dfs_combi(depth+1, i);
		vc.pop_back();
		visited[i] = 0;
	}
}
void dfs_permu_repetition(int depth) { // 중복 순열 : visited[]없음
	if (depth == 3) {
		printvc();
		return;
	}
	for (int i = 0; i < 5; i++) {
		vc.push_back(arr[i]);
		dfs_permu_repetition(depth + 1);
		vc.pop_back();
	}

}
void dfs_combi_repetition(int depth, int idx) { // 중복 조합 : visited[]없음, idx 변수 추가
	if (depth == 3) {
		printvc();
		return;
	}
	for (int i = idx; i < 5; i++) {
		vc.push_back(arr[i]);
		dfs_combi_repetition(depth + 1, i);
		vc.pop_back();
	}
}

int main() {
	cout << "순열" << endl; // 순서 상관 o
	dfs_permu(0); // 순열
	cout << "조합" << endl; // 순서 상관 x
	dfs_combi(0,0); // 조합

	cout << "중복 순열" << endl; // 순서 상관 x
	dfs_permu_repetition(0); // 중복 순열
	cout << "중복 조합" << endl; // 순서 상관 x
	dfs_combi_repetition(0,0); // 중복 조합
}

결과는 다음과 같다

0

정리

1
2
3
4
void dfs_permu(int depth) // 순열 : visited[]있음
void dfs_combi(int depth,int idx) // 조합 : visited[]있음, idx 변수 추가
void dfs_permu_repetition(int depth) // 중복 순열 : visited[]없음
void dfs_combi_repetition(int depth, int idx) // 중복 조합 : visited[]없음, idx 변수 추가

visited는 중복 되는 순열이나 조합을 뽑지 않기 위해 체크하는 배열.

조합과 순열의 큰 차이점은 dfs에서 for문을 돌 때, idx체크를 하는 지 안 하는지 이다.

  • 순열의 경우 순서가 상관 있기에 순서를 고려해 1 2 3 과 1 3 2 가 서로 다르지만
  • 조합의 경우 순서가 상관 없기에 1 2 3과 1 3 2가 의미하는 바가 같아 depth가 낮은 dfs에서 높은 depth의 dfs 함수를 들어갈 때 현재 idx보다 더 이후의 idx만 방문한다.