순열 (Permutation) - 교환방식
Algorithm/경우의 수
2022. 4. 11. 01:29
- 순열 (Permutation) -
n개의 수를 중복을 허용하지 않고(visited)
r개를 나열할 수 있는 모든 경우의 수 (1 ≤ r ≤ n)
문제인식)
1부터 3(n)까지의 수가 있다.
이들을 이용하여 3(r)개의 수를 중복없이 나열하고자 할 때
가능한 모든 경우를 각각 한 줄씩 출력하고자 한다면 어떻게 해야할까?
int n=3, r=3;
해결과정)
1) 현재위치(dpth)와 맞바꿀 위치(i)간에 swap을 진행한다. dpth는 재귀의 깊이이자 맞바꿀 위치의 시작.
2) 맞바꿀 위치(dpth)를 옮기기위해 다음 위치(dpth+1)로 재귀적 진입을 한다.
3) 깊은재귀가 끝나면 윈위치시킨다.(다시 swap)
(※ [더보기]를 클릭하면 C/C++ 소스코드를 참조할 수 있습니다.)
더보기
#include<iostream>
#include<vector>
using namespace std;
int n=3, r=3;
vector<int> v;
void Permutation(int r, int dpth) {
if(dpth>=r) {
//출력
for(int i=0; i<r; i++) printf("%d ", v[i]); printf("\n");
//종료
return;
}
for(int i=dpth; i<n; i++) { //i는 swap을 진행하기 위한 인덱스
swap(v[i], v[dpth]);
Permutation(r, dpth+1); //재귀진입
swap(v[i], v[dpth]);
}
}
int main() {
//수를 vector에 삽입
for(int i=1; i<=n; i++) v.push_back(i);
Permutation(r, 0);
return 0;
}
위 코드의 경우 시간복잡도는 당연히 O(n의 r제곱)이다.
주의점)
사실 이 방식은 오름차순으로 탐색이 되지 않는다.
위 그림에서도 보듯이 dpth가 1이될 때 3번째 그림은,
0과 2의 자리를 맞바꾸었기 때문에 "3 2 1 "이 되었다.
정상적인 순서라면 "3 1 2 "가 맞아야하는데 그 순서가 어긋났다.
이런 이유로 실제로 교환방식을 사용하는 것은
개인적으로 권장하지 않는다.
그러나 next_permutation(), prev_permutation() 함수는
swap방식인데도 오름차순, 내림차순 순서를 보장한다! (필자도 솔직히 어떻게 보장되는진 아직 모른다.)
이 두 함수에 대한 자세한 설명은 여기를 참조
응용)
수를 재귀적으로 위치를 맞바꾸는 방식이 아닌, 재귀적으로 삽입하는 방식으로 해보기
등
'Algorithm > 경우의 수' 카테고리의 다른 글
조합 (Combination) (0) | 2022.04.20 |
---|---|
순열 (Permutation) - 삽입방식 | (+중복순열, +함수사용) (0) | 2022.04.10 |