알고리즘/개념정리

순열

보름달빵 2025. 6. 21. 17:41

문제

10개 이하의 N개의 자연수가 주어지면, 그 중 M개를 뽑아 일렬로 나열하는 방법을 모두 출력하시오. 

 

입력

첫번째 줄에 결과를 출력합니다. 출력 순서는 사전순으로 오름차순으로 출력합니다. 

 

입력 예시

3 2

3 6 9

 

출력 예시 

3 6 

3 9

6 3

6 9

9 3

9 6 

 

 

풀이과정 

 

반복문과  DFS를 이용하여 순열을 구현할 수 있다. 

static int n,m;
static int[] arr;
static boolean [] visited;
static int[] answer;
  • 첫번째 줄에 주어진 자연수들을 저장하기 위한 배열 arr을 선언한다. 
  • 중복으로 선택되는것을 막기 위해 boolean 배열을 이용하여 한번 선택되었다면 방문처리를 해준다. 
  • 선택된 수를 저장하기 위해 answer 배열을 사용하여 기록한다. 

 

main 코드 
public static void main(String[] args) throws IOException {

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    StringTokenizer st = new StringTokenizer(br.readLine());

    n = Integer.parseInt(st.nextToken());
    m = Integer.parseInt(st.nextToken());

    arr = new int[n];
    answer = new int[m];
    visited = new boolean[n];


    st = new StringTokenizer(br.readLine());
    for(int i=0;i<n;i++){
        arr[i] = Integer.parseInt(st.nextToken());
    }

    dfs(0);
}
  • N개를 저장할 배열들을 만들고 초기화 한다. 
  • M개의 숫자를 저장할 수 있는 배열을 초기화 한다. (answer 배열은 마치 경로를 기록하는 용도)
  • 이후 반복문을 이용해 주어진 숫자들을 배열에 저장하고 dfs 함수를 호출한다. 

 

 

dfs 코드 
static void dfs(int L){
    if(L==m){
        for (int x : answer) {
            System.out.print(x+" ");
        }
        System.out.println();
    }else{
        for(int i=0;i<n;i++){
            if(!visited[i]){
                answer[L]=arr[i]; // 경로기록
                visited[i]=true; // 방문처리
                dfs(L + 1);
                visited[i]=false;
            }
        }
    }
}

 

 

 

if(L==m){
    for (int x : answer) {
        System.out.print(x+" ");
    }
    System.out.println();
}
  • 만약 호출 횟수가 m과 같아진다면, 재귀호출을 멈추고 지금까지 answer배열에 저장된 값들을 출력한다. 

 

else{
    for(int i=0;i<n;i++){
        if(!visited[i]){
            answer[L]=arr[i]; // 경로기록
            visited[i]=true; // 방문처리
            dfs(L + 1);
            visited[i]=false;
        }
    }
}
  • 아직 호출의 횟수가 m번 미만이라면, 재귀호출을 반복한다. 
  • 반복문을 통해 arr 배열을 탐색하며 아직 방문하지 않은 곳을 선택한다. 
  • 이때 경로를 기록하고 선택된 인덱스 값이, 재귀호출 이후에 또 다시 선택되는것을 막기위해 방문처리한다. 
  • 재귀호출이 끝난 이후에는 다시 방문 할 수 있도록 방문 처리했던 것을 취소해준다. 

 

 

전체코드 
package 섹션8_DFS_BFS심화;

import java.io.*;
import java.util.StringTokenizer;

public class Q6_순열구하기 {

    static int n,m;
    static int[] arr;
    static boolean [] visited;

    static int[] answer;

    static void dfs(int L){
        if(L==m){
            for (int x : answer) {
                System.out.print(x+" ");
            }
            System.out.println();
        }else{
            for(int i=0;i<n;i++){
                if(!visited[i]){
                    answer[L]=arr[i]; // 경로기록
                    visited[i]=true; // 방문처리
                    dfs(L + 1);
                    visited[i]=false;
                }
            }
        }
    }
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        arr = new int[n];
        answer = new int[m];
        visited = new boolean[n];


        st = new StringTokenizer(br.readLine());
        for(int i=0;i<n;i++){
            arr[i] = Integer.parseInt(st.nextToken());
        }

        dfs(0);
    }
}

'알고리즘 > 개념정리' 카테고리의 다른 글

유니온 파인드  (0) 2024.11.23
그래프를 구현하는 방법  (6) 2024.11.20
소수를 구하는 방법  (4) 2024.11.19
정렬  (0) 2024.07.10