https://www.acmicpc.net/problem/10972
10972번: 다음 순열
첫째 줄에 입력으로 주어진 순열의 다음에 오는 순열을 출력한다. 만약, 사전순으로 마지막에 오는 순열인 경우에는 -1을 출력한다.
www.acmicpc.net
[문제]
1부터 N까지의 수로 이루어진 순열이 있다. 이때, 사전순으로 다음에 오는 순열을 구하는 프로그램을 작성하시오.
사전 순으로 가장 앞서는 순열은 오름차순으로 이루어진 순열이고, 가장 마지막에 오는 순열은 내림차순으로 이루어진 순열이다.
N = 3인 경우에 사전순으로 순열을 나열하면 다음과 같다.
- 1, 2, 3
- 1, 3, 2
- 2, 1, 3
- 2, 3, 1
- 3, 1, 2
- 3, 2, 1
[입력]
첫째 줄에 N(1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄에 순열이 주어진다.
[출력]
첫째 줄에 입력으로 주어진 순열의 다음에 오는 순열을 출력한다. 만약, 사전순으로 마지막에 오는 순열인 경우에는 -1을 출력한다.
[예제 입력 1]
4
1 2 3 4
[예제 출력 1]
1 2 4 3
[예제 입력 2]
5
5 4 3 2 1
[예제 출력 2]
-1
[내 풀이]
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
/*
문제 : [S3] 다음 순열 - 10972번
제출 : 2024년 2월 13일
결과 : 통과
성능 요약 : 메모리 19672KB, 시간 400ms
아이디어 : Next Permutation을 이용해 풀었습니다.
내가 한 뻘짓 :
1. 순열 모두 구한 후 답 구하려고함.
2. 문자열로 입력받아서 처리하려고 함.
3. NP 제대로 이해 못한 상태로 풀려고함.
*/
public class Main_10972_다음순열_남보우 {
static int N, bindex, aindex;
static int[] ans;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
N = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
ans = new int[N];
for (int i=0; i<N; i++) {
ans[i] = Integer.parseInt(st.nextToken());
}
boolean isSwap = false;
for (int i=ans.length-1; i>0; i--) {
// 오르막길 끝
if (ans[i-1] < ans[i]) {
isSwap = true;
bindex = i-1;
int maxNum = -1;
// bindex의 위치한 값보다 큰 값중 가장 작은 값 찾음
for (int j=ans.length-1; j>=i; j--) {
if (ans[bindex] < ans[j]) {
maxNum = ans[j];
aindex = j;
break;
}
}
// 두 수를 스왑
swap(bindex, aindex);
// bindex이후 수들을 오름차순 정렬
for (int j=0; j<(N-bindex)/2; j++) {
swap(i + j, N-1-j);
}
break;
}
}
if (!isSwap) System.out.println(-1);
else {
for (int i=0; i<N; i++) {
System.out.print(ans[i] + " ");
}
}
}
// 수 교환
static void swap(int i, int j) {
int temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
}
}
<회고>
Next Permutation이라는 개념 자체를 이해하는 것이 어려웠고, 이해한 개념을 코드로 구현하는 것도 쉽지 않았다.
간단하게 이해한 Next Permutation 알고리즘을 설명하면 아래와 같다.
Next Permutation 알고리즘
1. 뒤쪽부터 탐색하여 교환위치(i-1)을 찾는다.
- 이때 i는 가장 높은 값(꼭대기)
2. 다시 뒤쪽부터 탐색하여 (i-1)인덱스에 위치한 값보다 큰 수중 가장 작은수를 찾는다.
3. 두 수를 교환한다.
4. 꼭대기 위치(i)부터 맨 뒤까지 다시 오름차순으로 정렬한다.
'Algorithm > Java' 카테고리의 다른 글
[BOJ] 5373 : 큐빙 [P5] (0) | 2024.03.10 |
---|---|
[BOJ] 7576 : 토마토 [G5] (0) | 2024.03.09 |
[BOJ] 4179 : 불! [G4] (0) | 2024.02.12 |
[SWEA] 1233. 사칙연산유효성검사 [D4] (1) | 2024.02.07 |
[BOJ] 3055 : 탈출 [G4] (1) | 2024.02.07 |