순열
순열
- 하나의 집합을 다른 순서로 뒤섞는 것
- n개의 집합에서 순열의 총 개수는 n!
ex) n = 5, 5x4x3x2x1 = 순열의 총 개수 - nPr 수식 (P = Permutation 약자)
3P2 = 3! / (3-2)!
= 6 / 1
= 6 (1, 2) / (1, 3) / (2, 1) / (2, 3) / (3, 1) / (3, 2) 총 6개 - 재귀로 구현 가능
자주 사용되는 swap, visited 방법으로 구현 - 완전탐색 문제에서도 자주 나올 수 있음
swap을 이용한 순열
- 배열의 값을 직접 교환해서 구함
- Depth를 이용한 풀이
- Depth와 r의 값이 같으면 모두 다 뽑았다는 것이므로 결과값 출력
- 순열 함수가 종료됐을 때 배열의 값을 다시 원상복구 해주어야 함
(그 다음 수와 다시 순열을 계산해야 하므로)
구현
주석으로 설명했으나, 제일 빠른건 직접 디버깅하면서 확인해보면 된다.
public static void swapPermutation(int[] arr, int depth, int n, int r) {
// depth와 r이 같으면 다 뽑았다는 것이므로
if (depth == r){
for(int i=0; i<r; i++){
System.out.print(arr[i] + " ");
}
System.out.println();
return;
}
else {
/*
1, 2, 3 세 개의 숫자를 순열로 구한다고 했을 때,
재귀의 특성 상
depth가 0일 경우 1XX, 2XX, 3XX을 구해야 함
depth가 1일 경우 12X, 13X 를 구해야 함
depth가 2일 경우 123, 132 를 구해야 함
depth == r에서 return 되면서 배열을 원상복구 시킨 후
depth가 0일 경우 2XX, 3XX 를 구하는 과정을 반복
*/
for(int i=depth; i<n; i++){
swap(arr, i, depth);
swapPermutation(arr, depth + 1, n, r);
swap(arr, i, depth);
}
}
}
public static void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
visited을 이용한 순열
- 방문했는지 확인할 수 있는 visited 배열과, 결과를 저장할 수 있는 result 배열이 필요함
- Depth를 이용한 풀이
- Depth와 r의 값이 같으면 모두 다 뽑았다는 것이므로 결과값 출력
- visited를 통해 result에 데이터 저장 시 중복값이 들어가지 않도록 함
구현
public static void visitedPermutation(int[] arr, boolean[] visited, int[] result, int depth, int n, int r) {
if (depth == r){
for(int i : result){
System.out.print(i + " ");
}
System.out.println();
return;
}
else {
for(int i=0; i<n; i++){
if (!visited[i]){
visited[i] = true;
result[depth] = arr[i];
visitedPermutation(arr, visited, result, depth + 1, n, r);
visited[i] = false;
}
}
}
}
결과비교
결과를 살펴보면 아래와 같다.
swap을 이용한 순열과 visited를 이용한 순열의 데이터를 비교해보면,
swap에서는 3, 2, 1 / 3, 1, 2 순으로 출력이 되는데 visited에서는 3, 1, 2 / 3, 2, 1 순으로 출력이 된다.
따라서 swap을 이용해서 순열을 구했을 때는 순서대로 순열이 구해지지 않는다는 차이점을 발견할 수 있다.
'0x20. 알고리즘 > 0x21. 이론' 카테고리의 다른 글
[JAVA] 삽입 정렬 (Insertion Sort) (0) | 2021.11.04 |
---|---|
[JAVA] 선택 정렬 (Selection Sort) (0) | 2021.11.03 |
[JAVA] 버블 정렬 (Bubble Sort) (0) | 2021.11.02 |
깊이 우선 탐색 (DFS, Depth-First Search) (0) | 2021.10.08 |
그리디(Greedy) 알고리즘 (탐욕 알고리즘) (0) | 2021.10.05 |