--> 2019. 6. 12 수정
n이 입력으로 주어지면
모든 순열을 출력하면 되는 문제이다.
다음 순열을 계속해서 구하는 방법과
백트래킹을 사용해서 구하는 방법
두 가지 방법을 알아보자.
먼저 순열을 사용한 방법이다.
크기가 n인 배열의 순열의 개수는 n!이다.
n! 만큼 다음 순열을 구한 다음 계속 출력해주면 되는 문제이다.
다음 순열을 구하는 방법을 까먹었다면
https://dundung.tistory.com/58
이 글을 보도록 하자.
다음 순열을 구하는 메소드의 수행시간은 O(n)이다.
길이가 n인 배열의 순열의 개수는 n!이므로
모든 순열을 구하는 수행시간은 O(n!*n)이다
모든 순열을 구할 땐 do while문을 사용하는 것이 가장 올바른 방법이다.
알고리즘 문제를 풀 때 do while을 잘 사용하지 않는데
다음 순열을 구할 땐 가장 많이 사용한다.
다음 순열을 구하는 메소드는 이전 글과 똑같고 메인메소드만 조금 다르다.
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
|
public class Q10974 {
static void swap(int [] a , int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
static boolean nextPermutation(int [] a) {
int i = a.length-1;
while(i > 0 && a[i] <= a[i-1]) {
i--;
}
if(i <= 0) {
return false;
}
int j = a.length-1;
while(a[i-1] >= a[j]) {
j--;
}
swap(a, i-1, j);
j = a.length-1;
while(i < j) {
swap(a, i, j);
i++;
j--;
}
return true;
}
public static void main(String [] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int [] a = new int[n];
for(int i=1; i<=n; i++) {
a[i-1] = i;
}
do {
for(int i=0; i<n; i++) {
System.out.print(a[i]+" ");
}
System.out.println();
} while(nextPermutation(a));
}
}
|
이번엔 백트래킹으로 구하는 방법이다.
백트래킹은 내가 이해한 바로는
마지막 것을 지워줌으로써 재귀 호출로 되추적을 하는 방식이다.
https://www.youtube.com/watch?v=wxQmnEKNXAM
이 동영상에서 굉장히 자세하고 친절하게 백트래킹으로 모든 순열을 구하는 방법을 설명해준다.
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
|
import java.util.ArrayList;
import java.util.List;
public class Q10974_ver2 {
public static void backtrack(List<List<Integer>> list, List<Integer> tmp, int [] nums) {
list.add(new ArrayList<>(tmp));
return;
}
for(int num : nums) {
if(!tmp.contains(num)){
tmp.add(num);
backtrack(list, tmp, nums);
}
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int [] nums = new int[n];
List<List<Integer>> list = new ArrayList<>();
List<Integer> tmp = new ArrayList<>();
for(int i=1; i<=n; i++) {
nums[i-1] = i;
}
backtrack(list, tmp, nums);
for(List<Integer> k : list) {
for(int i=0; i<n; i++) {
System.out.print(k.get(i)+" ");
}
System.out.println();
}
}
}
|
백트래킹 코드가 훨씬 간단하다는 것을 알 수 있다.
시간은 순열이 조금 더 빠른 것 같다.
'Algorithm' 카테고리의 다른 글
백준 10971 외판원 순회 2 Java (0) | 2019.05.31 |
---|---|
백준 1722 순열의 순서 Java (0) | 2019.05.29 |
백준 10972 이전 순열 & 10973 다음 순열 Java (0) | 2019.05.28 |
비트마스크 (0) | 2019.05.27 |
백준 1561 놀이공원 Java (0) | 2019.05.27 |