백준 15663번_ N과 M (9)
N개의 자연수와 자연수 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오. N개의 자연수 중에서 M개를 고른 수열 **입력** 첫째 줄에 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8) 둘째 줄에 N개의 수가 주어진다. 입력으로 주어지는 수는 10,000보다 작거나 같은 자연수이다. **출력** 한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해야 한다. 예제 입력 1 3 1 4 4 2 예제 출력 1 2 4 예제 입력 2 4 2 9 7 9 1 예제 출력 2 1 7 1 9 7 1 7 9 9 1 9 7 9 9 예제 입력 3 4 4 1 1 1 1 예제 출력 3 1 1 1 1위 문제에서는 순열끼리의 중복을 한 번 더 체크해야 했다.
N과 M 문제들 1번과 2번에서는 숫자끼리의 중복을 한 번 체크한 후에는 숫자들이 오름차순으로 순차적으로 선택되므로 순열이 중복되지 않는다. 하지만 위 문제에서는 숫자값이 아닌 각 숫자의 저장 위치의 중복을 확인해야 했고, 순열의 중복이 보장되지 않았기 때문에 가장 깊은 재귀 호출 시에 저장된 숫자 리스트의 값이 달라진다.풀이 방향
- 가장 깊은 재귀 함수 호출 시 완성된 순열을 Set
<String>에 넣어서 바로바로 중복된 순열을 제거하고, List로 변환해 sort해준 후 출력하는 방식으로 풀이했다. 하지만 이 경우 문제가 있다. 마지막 sort 과정에서 String 값으로 두 원소를 비교하는데, 순열의 숫자가 10 이상일 때는, String에서는 (숫자 하나씩 정렬하기 때문에) 정확한 정렬이 되지 않는다. 그러므로, 다음과 같이 바꾸어 풀이했다.
import java.util.*;
import java.io.*;
public class Main {
static int n;
static int m;
static boolean[] visited;
static int[] seq;
static StringBuilder allSeq;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
visited = new boolean[n + 1];
seq = new int[m];
allSeq = new StringBuilder();
int depth = 0;
for (int i = 1; i <= n; i ++) {
visited[i] = true;
seq[depth] = i;
recur_f(depth + 1);
visited[i] = false;
}
System.out.println(allSeq);
}
public static void recur_f(int depth) {
if(depth == m) {
for (int s : seq) {
allSeq.append(s).append(" ");
}
allSeq.append("\n");
return;
}
for (int i = 1; i <= n; i ++) {
if (!visited[i]) {
visited[i] = true;
seq[depth] = i;
recur_f(depth + 1);
visited[i] = false;
}
}
}
}
import java.util.StringTokenizer;
import java.io.*;
public class Main {
static int n;
static int m;
static boolean[] visited;
static int[] seq;
static StringBuilder allSeq;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
visited = new boolean[n + 1];
seq = new int[m];
allSeq = new StringBuilder();
int depth = 0;
for (int i = 1; i <= n; i ++) {
visited[i] = true;
seq[depth] = i;
recur_f(i, depth + 1);
visited[i] = false;
}
System.out.print(allSeq);
}
public static void recur_f(int i, int depth) {
if(depth == m) {
for (int s : seq) {
allSeq.append(s).append(" ");
}
allSeq.append("\n");
return;
}
for (int j = i + 1; j <= n; j ++) {
if (!visited[j]) {
visited[j] = true;
seq[depth] = j;
recur_f(j, depth + 1);
visited[j] = false;
}
}
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
import java.io.*;
//3일차_#8: 15663_N과 M (9)
public class Main {
static int n;
static int m;
static int[] nums;
static boolean[] visited;
static List<int[]> seqList;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
nums = new int[n];
visited = new boolean[n];
seqList = new ArrayList<>();
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i ++) {
nums[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(nums);
int depth = 0;
for (int i = 0; i < n; i ++) {
int k = nums[i];
visited[i] = true;
int[] seq = new int[m];
seq[depth] = k;
recur_f(seq, depth + 1);
visited[i] = false;
}
StringBuilder sb = new StringBuilder();
int[] prevSeq = seqList.get(0);
for (int s : prevSeq) {
sb.append(s).append(" ");
}
sb.append("\n");
for (int k = 1; k < seqList.size(); k ++) {
int[] sortedSeq = seqList.get(k);
if (!Arrays.equals(prevSeq, sortedSeq)) {
for (int s : sortedSeq) {
sb.append(s).append(" ");
}
sb.append("\n");
prevSeq = sortedSeq;
}
}
System.out.print(sb);
}
public static void recur_f(int[] prev_seq, int depth) {
if(depth == m) {
seqList.add(prev_seq);
return;
}
for (int i = 0; i < n; i ++) {
if (!visited[i]) {
int[] seq = Arrays.copyOf(prev_seq, prev_seq.length);
int k = nums[i];
visited[i] = true;
seq[depth] = k;
recur_f(seq,depth + 1);
visited[i] = false;
}
}
}
}