일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 17136
- 연산자 끼워넣기
- 17144
- 알고리즘
- 괄호추가하기
- 구슬탈출2
- Ajax
- 미세먼지 안녕!
- 부분수열의 합
- 14502
- 좋아요
- Java
- 14888
- 로또
- 재귀
- 댓글
- 백준
- 따라하기
- 장고
- django
- 다리 만들기2
- 색종이 붙이기
- 17143
- 17472
- 1182
- 9095
- 16637
- 인스타그램
- 인스타
- 6603
- Today
- Total
Be a developer
백준 10972 다음 순열 본문
순열은 순서가 부여된 임의의 집합을 다른 순서로 뒤섞는 연산이다.
다음 순서의 순열을 찾으려면 c++에서는 next_permutation과 prev_permutation이 존재하기 때문에 사용하면 된다.
직접 구현하기 위한 방법은 아래와 같다.
1. A[i-1] < A[i]를 만족하는 가장 큰 i를 찾는다.(이 말은 i-1 index 이후의 순열은 내림차순으로 정렬되어 있다는 말이다.)
2. j>=i 이면서 A[j] > A[i-1] 를 만족하는 가장 큰 j를 찾는다.(다음 순열은 순열을 하나의 수로 봤을 때 더 큰 수가 되어야 하므로, A[i-1]보다 큰 수를 앞으로 가져와야 한다. 작은 수를 앞으로 가져오는 것은 작은 수로 바꾸는 것이기 때문이다.)
3. A[i-1]과 A[j]를 swap한다.
4. A[i]부터 순열을 뒤집는다.(i-1 index 이후는 내림차순이기 때문에 오름차순으로 정렬하기 위해 순열을 swap하여 뒤집어 준다.)
순열 2317645을 예시로 들겠다.
처음에는 2<3이고 3<1이기 때문에 i를 1이라고 생각했다. 하지만 조건을 만족하는 가장 큰 i이기 때문에
4<5도 조건을 만족하게 되어 i는 6이 된다. 따라서 j는 6이 되고, 4와 5를 swap하게 된다. 4번 과정에 해당되는 것이 없기 때문에 2317645의 다음 순열은 2317654가 된다.
만약 2317654의 다음 순열을 구한다면, 1<7일 때 가장 큰 i가 나오게 된다. 따라서 i는 3이 된다.
A[i-1]의 값은 1이 되고, i+1의 인덱스부터 끝까지 탐색하면서 A[j] > A[i-1]을 만족하는 j를 찾는다. 결과적으로 j는 6이 되고, 1과 4를 swap하게 된다. 2317654 => 2347651이 된다.
마지막으로 4번 과정을 거치면 2341567이 된다.
즉, 2317654의 다음 순열은 2341567이 되는 것이다.
마지막 예시는 7236541이다.
i는 3이고, A[i-1]은 3이다. j는 5가 되고 A[j]는 4가 된다. 따라서 3과 4를 swap하고, A[i]부터 순열을 뒤집는다.
결과적으로 7236541의 다음 순열은 7241356이 된다.
1번 과정에서 O(N)
2번 과정에서 O(N)
3번 과정에서 O(1)
4번 과정에서 O(N) 이다.
각각 독립적이므로 총 시간 복잡도는 O(N)이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <iostream> #include <algorithm> #include <vector> using namespace std; int main() { int n; cin >> n; vector<int> a(n); for (int i=0; i<n; i++) { cin >> a[i]; } if (next_permutation(a.begin(),a.end())) { for (int i=0; i<n; i++) { cout << a[i] << ' '; } } else { cout << "-1"; } cout << '\n'; return 0; } | cs |
------------------------------------------------------------------------------------------------------------------------------
다음 순열을 구하는데 필요한 시간 복잡도는 N * N!이다. 순열을 구하는데 N!이 필요하고, 다음 순열 계산을 위해 N이 필요하기 때문이다. N * N!이 1억이 넘지 않게 하려면 N은 최대 10이 될 수 있다.
따라서 순열을 구하는 문제에서 N의 크기가 어떻게 되는지 알아야 한다.
- 3! = 6
- 4! = 24
- 5! = 120
- 6! = 720
- 7! = 5,040
- 8! = 40,320
- 9! = 362,880
- 10! = 3,628,800
- 11! = 39,916,800
'알고리즘' 카테고리의 다른 글
알고리즘 풀면서 참고할 사항들 (0) | 2019.03.27 |
---|---|
백준 10819 차이를 최대로 (0) | 2019.03.27 |
백준 9095 1,2,3 더하기 (0) | 2019.03.27 |
백준 14500 테트로미노 (0) | 2019.03.27 |
백준 1476 날짜 계산 (0) | 2019.03.26 |