자바 코딩테스트 강좌, 선물 전달하기

코딩 테스트를 준비하는 과정에서 여러 알고리즘 문제를 접하게 됩니다. 이번 강좌에서는 ‘선물 전달하기’라는 주제를 가지고 문제를 이해하고 해결하는 과정을 자세히 살펴보겠습니다. 이 문제는 그래프 탐색 및 분배 문제의 복합적인 요소를 가지고 있어, 코딩 테스트에서 자주 등장하는 유형입니다.

문제 설명

어느 날, N명의 친구들이 모여 서로에게 선물을 주기로 했습니다. 친구들은 특정한 규칙에 따라 선물을 주는데, 각 친구는 자신이 선물을 줄 수 있는 친구의 목록을 가지고 있습니다. 선물을 주는 방향과 수는 정해져 있으며, 모든 친구는 반드시 하나의 선물을 받아야 합니다.

우리의 목표는 가능한 모든 경우의 수를 계산하여, 친구들이 서로에게 선물을 주고받는 방법의 총 가짓수를 구하는 것입니다. 문제의 입력은 친구의 수 N과 각 친구가 선물을 줄 수 있는 친구의 인덱스 목록으로 주어집니다.

문제 예시

    입력:
    4
    1 2
    2 3
    3 4
    4 1

    출력:
    4
    

위의 예시에서 4명의 친구가 상호적으로 선물을 주고받는 경우의 수는 4가지입니다. 이러한 경우를 찾아내는 것이 우리의 주요 목표입니다.

알고리즘 설계

이 문제를 해결하기 위해서는 그래프 이론을 활용하는 것이 효율적입니다. 친구들을 정점으로 보고, 선물을 줄 수 있는 관계를 간선으로 나타내면 이 문제는 방향 그래프의 형태로 변환됩니다. 이제 이 그래프에서 강한 연결 요소를 찾아야 합니다. 이를 통해 모든 친구가 선물을 주고받을 수 있도록 하는 방법의 수를 계산할 수 있습니다.

우리가 사용할 알고리즘은 다음과 같습니다:

  • 그래프를 구성한다.
  • 강한 연결 요소(Strongly Connected Components)를 찾는다.
  • 각 연결 요소에서 가능한 모든 선물 전달 방법의 수를 계산한다.
  • 각 연결 요소의 방법 수를 곱하여 최종 답을 도출한다.

구현

이제 자바를 사용하여 이 알고리즘을 구현해봅시다. 다음은 그 코드입니다:

    import java.util.*;

    public class GiftDistribution {
        static int N;
        static List> graph = new ArrayList<>();
        static boolean[] visited;
        static Stack stack = new Stack<>();
        static List> scc = new ArrayList<>();

        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            
            // 입력 받기
            N = sc.nextInt();
            for (int i = 0; i < N; i++) {
                graph.add(new ArrayList<>());
                int count = sc.nextInt();
                for (int j = 0; j < count; j++) {
                    graph.get(i).add(sc.nextInt() - 1);
                }
            }

            visited = new boolean[N];
            // 그래프의 모든 정점에 대해 DFS 수행
            for (int i = 0; i < N; i++) {
                if (!visited[i]) {
                    dfs(i);
                }
            }

            // 전이 그래프 생성
            List> reverseGraph = new ArrayList<>();
            for (int i = 0; i < N; i++) {
                reverseGraph.add(new ArrayList<>());
            }
            for (int i = 0; i < N; i++) {
                for (int neighbor : graph.get(i)) {
                    reverseGraph.get(neighbor).add(i);
                }
            }

            Arrays.fill(visited, false);
            // SCC 찾기
            while (!stack.isEmpty()) {
                int v = stack.pop();
                if (!visited[v]) {
                    List component = new ArrayList<>();
                    reverseDfs(v, component, reverseGraph);
                    scc.add(component);
                }
            }

            // 경우의 수 계산
            int result = 1;
            for (List component : scc) {
                result *= factorial(component.size());
            }
            System.out.println(result);
        }

        static void dfs(int v) {
            visited[v] = true;
            for (int neighbor : graph.get(v)) {
                if (!visited[neighbor]) {
                    dfs(neighbor);
                }
            }
            stack.push(v);
        }

        static void reverseDfs(int v, List component, List> reverseGraph) {
            visited[v] = true;
            component.add(v);
            for (int neighbor : reverseGraph.get(v)) {
                if (!visited[neighbor]) {
                    reverseDfs(neighbor, component, reverseGraph);
                }
            }
        }

        static int factorial(int n) {
            int fact = 1;
            for (int i = 1; i <= n; i++) {
                fact *= i;
            }
            return fact;
        }
    }
    

코드 설명

코드는 다음과 같은 과정으로 이루어져 있습니다:

  1. 그래프의 입력 처리: 각 친구가 줄 수 있는 친구의 목록을 입력 받아 그래프를 구성합니다.
  2. DFS를 이용한 스택 생성: 모든 정점에 대해 깊이 우선 탐색을 수행하고, 방문 후 스택에 추가합니다.
  3. 전이 그래프 만들기: 원래 그래프의 간선을 반대로 하여 전이 그래프를 생성합니다.
  4. SCC 찾기: 스택에서 정점을 하나씩 꺼내고, 전이 그래프를 통해 SCC를 찾습니다.
  5. 경우의 수 계산: 각 SCC의 크기에 대한 팩토리얼을 계산하여 최종 결과를 도출합니다.

복잡도 분석

이 알고리즘의 시간 복잡도는 O(N + E)입니다. 여기서 N은 노드의 수, E는 간선의 수를 의미합니다. 또한, 공간 복잡도 또한 O(N + E)로, 그래프를 저장하기 위한 공간이 필요합니다.

마무리

이번 강좌를 통해 ‘선물 전달하기’ 문제를 해결하는 방법을 알아보았습니다. 알고리즘의 구현 과정과 복잡도 분석까지 자세히 살펴보았습니다. 이러한 문제는 코딩 테스트뿐만 아니라 실제 프로젝트에서도 종종 마주칠 수 있기 때문에, 그래프 이론 및 알고리즘에 대한 이해를 깊이 하는 것이 중요합니다.

여기서 다룬 내용을 바탕으로 연습문제를 풀어보며 실력을 쌓아보시기 바랍니다. 다음 강좌에서는 또 다른 알찬 문제로 찾아뵙겠습니다!

자바 코딩테스트 강좌, 삽입 정렬

안녕하세요! 이번 편에서는 자바 프로그래밍 언어를 이용한 코딩 테스트에서 자주 출제되는 알고리즘 중 하나인 ‘삽입 정렬(Insertion Sort)’에 대해 다루어보겠습니다. 삽입 정렬은 비교 기반의 정렬 알고리즘으로, 효율성과 간결함 덕분에 초급 프로그래머들 사이에서 널리 사용됩니다. 이 글에서는 삽입 정렬의 이론적 배경, 문제를 통해 정렬 알고리즘을 구현하고 그 과정을 자세히 설명할 것입니다.

삽입 정렬(Insertion Sort)란?

삽입 정렬은 정렬되지 않은 데이터를 하나씩 정렬된 부분으로 삽입해가는 방식의 정렬 알고리즘입니다. 이 알고리즘은 카드 게임에서 카드를 정리하는 방식과 유사하다고 생각할 수 있습니다. 즉, 여러분은 카드를 하나씩 꺼내어 이미 정렬된 카드 뭉치에 적절한 위치에 삽입하는 것입니다.

삽입 정렬의 알고리즘 동작 과정

  1. 정렬된 부분과 정렬되지 않은 부분으로 나누어져 있는 배열을 생각합니다.
  2. 정렬되지 않은 부분에서 첫 번째 원소를 선택합니다.
  3. 정렬된 부분에서 선택된 원소의 위치를 찾아 삽입합니다.
  4. 위 과정을 정렬되지 않은 원소가 없을 때까지 반복합니다.

이 알고리즘의 시간 복잡도는 최악의 경우 O(n^2), 최선의 경우 O(n) 및 평균적으로 O(n^2)입니다. 그러나 적은 양의 데이터에 대해 느린 성능을 가지므로, 대규모 데이터셋에는 다른 정렬 알고리즘(예: 퀵 정렬, 힙 정렬 등)이 더 적합할 수 있습니다.

알고리즘 문제: 삽입 정렬 구현하기

다음은 삽입 정렬 알고리즘을 구현하는 문제입니다.

문제 설명

주어진 정수 배열을 오름차순으로 정렬하는 함수를 작성하시오.

입력

배열의 길이 n (1 ≤ n ≤ 1000)
정수 배열 a (1 ≤ a[i] ≤ 10^6)

출력

오름차순으로 정렬된 배열

입력 예시

5
5 2 9 1 5

출력 예시

1 2 5 5 9

문제 풀이 과정

이 문제를 해결하기 위해, 다음의 단계를 따라 삽입 정렬 알고리즘을 자바로 구현해보겠습니다.

1. 배열 입력 받기

우선 배열의 길이와 배열 요소를 입력 받는 작업이 필요합니다. 이 작업은 자바의 Scanner 클래스를 사용하여 쉽게 수행할 수 있습니다.

import java.util.Scanner;

public class InsertionSort {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 배열의 길이 입력 받기
        int n = scanner.nextInt();
        int[] arr = new int[n];
        
        // 배열 요소 입력 받기
        for (int i = 0; i < n; i++) {
            arr[i] = scanner.nextInt();
        }
    }
}

2. 삽입 정렬 알고리즘 구현

다음으로, 삽입 정렬 알고리즘을 구현합니다. 주요 아이디어는 현재 요소를 이전 요소들과 비교하여 적절한 위치에 삽입하는 것입니다. 이를 구현하기 위해 내포된 반복문을 사용할 것입니다.

public static void insertionSort(int[] arr) {
    int n = arr.length;

    for (int i = 1; i < n; i++) {
        int key = arr[i]; // 현재 비교할 요소
        int j = i - 1;

        // key 보다 더 큰 요소들을 한 칸씩 이동
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        // key를 적절한 위치에 삽입
        arr[j + 1] = key;
    }
}

3. 배열 출력하기

정렬이 완료된 배열을 출력하기 위해 간단한 출력 함수를 작성합니다.

public static void printArray(int[] arr) {
    for (int i = 0; i < arr.length; i++) {
        System.out.print(arr[i] + " ");
    }
    System.out.println();
}

4. 전체 프로그램 통합

마지막으로, 위의 모든 기능을 메인 메서드에 통합하여 전체 프로그램을 작성합니다.

public class InsertionSort {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] arr = new int[n];

        for (int i = 0; i < n; i++) {
            arr[i] = scanner.nextInt();
        }

        insertionSort(arr);
        printArray(arr);
    }

    public static void insertionSort(int[] arr) {
        int n = arr.length;
        for (int i = 1; i < n; i++) {
            int key = arr[i];
            int j = i - 1;
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = key;
        }
    }

    public static void printArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

결론

이번 강좌에서는 자바를 사용하여 삽입 정렬 알고리즘을 구현하는 방법을 배웠습니다. 삽입 정렬은 알고리즘의 기초를 이해하는 데 도움을 주며, 실력 향상에 큰 기여를 할 수 있습니다. 알고리즘 문제풀이에서 자주 출제되는 주제이므로, 충분히 연습하시길 바랍니다. 삽입 정렬의 장단점을 이해하고, 더 나아가 다른 정렬 알고리즘과 비교하는 것도 좋은 학습 방법입니다.

마지막으로, 알고리즘 문제풀이와 코딩 테스트 준비를 위해, 더욱 다양한 문제를 풀고, 알고리즘을 체계적으로 공부할 것을 추천드립니다. 감사합니다!

자바 코딩테스트 강좌, 사전 찾기

문제 설명

여러분은 여러 단어들로 구성된 사전을 가지고 있습니다. 이 사전에서 특정 단어가 있는지 여부를 확인하고,
그 단어의 의미를 출력하는 프로그램을 만들어야 합니다.

입력으로는 사전의 단어 리스트와 사용자가 입력한 단어가 주어집니다. 만약 사용자가 입력한 단어가
사전에 없으면 “단어를 찾을 수 없습니다.”라는 메시지를 출력해야 합니다.

입력 사항

  • 첫 번째 줄에는 정수 N이 주어집니다 (1 ≤ N ≤ 100,000).
  • 다음 N개의 줄에는 사전의 단어들이 주어집니다.
  • 마지막 줄에는 사용자가 검색할 단어가 주어집니다.

출력 사항

사용자가 입력한 단어의 의미를 출력하되, 단어가 사전에 없으면 “단어를 찾을 수 없습니다.”라고 출력합니다.

예시

입력:
5
apple
banana
grape
orange
pear
grape

출력:
"grape": 포도
입력:
5
apple
banana
grape
orange
pear
watermelon

출력:
단어를 찾을 수 없습니다.

문제 해결 전략

이 문제는 단어의 검색을 수행해야 하므로, 효율적인 데이터 구조를 선택하는 것이 핵심입니다.
해시맵(HashMap)을 사용하면 평균적으로 O(1)의 시간 복잡도로 단어를 검색할 수 있습니다.
따라서 사전을 해시맵에 저장한 다음, 사용자로부터 입력받은 단어를 해시맵에서 검색하여
의미를 출력하는 방식으로 문제를 해결할 수 있습니다.

자바 코드 구현

아래는 위의 문제를 해결하기 위한 자바 코드입니다. 이 코드는 해시맵을 사용하여 사전을 구현하고,
사용자 입력을 처리합니다.

import java.util.HashMap;
import java.util.Scanner;

public class DictionarySearch {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 사전의 단어 수 입력
        int N = scanner.nextInt();
        scanner.nextLine(); // 개행 문자 제거
        
        // 해시맵 초기화
        HashMap dictionary = new HashMap<>();
        
        // 사전 단어와 의미 입력
        for (int i = 0; i < N; i++) {
            String word = scanner.nextLine(); // 단어 입력
            String meaning = scanner.nextLine(); // 의미 입력
            dictionary.put(word, meaning);
        }
        
        // 검색할 단어 입력
        String searchWord = scanner.nextLine();
        
        // 단어 검색 및 출력
        if (dictionary.containsKey(searchWord)) {
            System.out.println("\"" + searchWord + "\": " + dictionary.get(searchWord));
        } else {
            System.out.println("단어를 찾을 수 없습니다.");
        }

        scanner.close();
    }
}

코드 설명

1. Scanner 클래스를 이용해 사용자 입력을 처리하고, HashMap을 사용해 사전을 저장합니다.
2. 먼저 사전의 크기 N을 입력받고, 입력한 만큼 반복하여 단어와 그 의미를 해시맵에 추가합니다.
3. 다음으로 사용자가 검색할 단어를 입력받아, 해시맵에 해당 단어가 있는지 확인합니다.
4. 만약 단어가 존재하면 그 의미를 출력하고, 존재하지 않으면 “단어를 찾을 수 없습니다.”라는 메시지를 출력합니다.

복잡도 분석

– 시간 복잡도: 단어를 해시맵에 추가하는 데 O(1), 검색하는 데 O(1)입니다. 전체적으로 O(N)입니다.
– 공간 복잡도: 해시맵에 N개의 단어와 각각의 의미를 저장하므로 O(N)입니다.

마무리

이번 글에서는 자바를 이용해 사전에서 특정 단어를 찾는 알고리즘 문제를 함께 살펴보았습니다.
해시맵을 사용하여 효율적으로 단어를 검색하는 방법을 배웠고, 문제 해결 과정을 통해 코딩테스트에서
어떤 접근 방식을 취해야 하는지에 대한 통찰을 얻었기를 바랍니다.
앞으로의 코딩테스트에서 이와 같은 문제를 만났을 때 자신감을 가지고 해결할 수 있기를 바랍니다.

자바 코딩테스트 강좌, 블루레이 만들기

코딩테스트는 소프트웨어 엔지니어링 분야에서 점점 더 중요해지는 요소 중 하나입니다. 이 글에서는 자바를 활용하여 복잡한 알고리즘 문제를 해결하는 데 필요한 기술을 익히는 방법에 대해 설명하고, ‘블루레이 만들기’라는 주제로 한 문제를 다루어 보겠습니다.

문제 설명

요구사항: 주어진 영화 리스트와 각 영화의 재생 시간을 바탕으로 블루레이의 용량을 고려하여 최소한의 블루레이 개수를 사용하여 모든 영화를 재생할 수 있는 방법을 찾으세요. 블루레이 하나에 담을 수 있는 최대 용량은 지정되어 있습니다.

입력:

  • maxSize: 각 블루레이의 최대 용량 (정수)
  • movies: 영화의 재생 시간 리스트 (정수 배열)

출력:

  • 모든 영화를 재생하기 위해 필요한 최소 블루레이 개수 (정수)

예시


maxSize: 10
movies: [1, 2, 3, 4, 5, 6]
출력: 3

문제 접근 방법

이 문제를 해결하기 위해서는 다음의 단계로 접근할 수 있습니다:

  1. 블루레이 하나의 용량을 초과하지 않도록, 가능한 많은 영화를 추가하는 방법을 고려합니다.
  2. 영화 리스트를 정렬하여 짧은 영화부터 긴 영화 순으로 재생하도록 합니다.
  3. 각 블루레이의 재생 시간을 계산하여 최대 용량을 초과하면 새로운 블루레이가 필요하도록 합니다.
  4. 필요한 블루레이 개수를 카운트합니다.

자바 코드 구현


import java.util.Arrays;

public class BluRayMaker {
    
    public static int minBluRays(int maxSize, int[] movies) {
        Arrays.sort(movies); // 영화를 정렬합니다.
        int bluRayCount = 0;
        int currentBluRaySize = 0;

        for (int i = movies.length - 1; i >= 0; i--) {
            // 현재 블루레이에 영화를 추가합니다.
            if (currentBluRaySize + movies[i] <= maxSize) {
                currentBluRaySize += movies[i];
            } else {
                // 블루레이의 용량을 초과하는 경우 새로운 블루레이를 사용합니다.
                bluRayCount++;
                currentBluRaySize = movies[i]; // 현재 영화로 블루레이를 시작합니다.
            }
        }

        // 남아 있는 블루레이가 있으면 카운트를 추가합니다.
        if (currentBluRaySize > 0) {
            bluRayCount++;
        }

        return bluRayCount;
    }

    public static void main(String[] args) {
        int maxSize = 10;
        int[] movies = {1, 2, 3, 4, 5, 6};
        System.out.println("최소 필요한 블루레이 개수: " + minBluRays(maxSize, movies));
    }
}

코드 설명

위의 코드에서는 블루레이를 만들기 위한 클래스를 정의하고, 최적의 영화 선택 방법을 구현하였습니다. 코드는 다음과 같은 방식으로 작동합니다:

  1. 영화 리스트를 정렬하여 가장 긴 영화부터 순서대로 처리합니다.
  2. 현재 블루레이의 재생 시간이 최대 용량을 넘지 않도록 영화를 추가합니다.
  3. 용량을 초과할 경우, 현재 블루레이를 종료하고 새로운 블루레이를 시작합니다.
  4. 모든 영화를 처리한 후 마지막 블루레이가 남아 있을 경우 추가 카운트합니다.

분석 및 복잡도

이 문제의 시간 복잡도는 O(N log N)입니다. 이는 주어진 영화 리스트를 정렬하는 데 필요한 시간입니다. 이후 영화 리스트를 한 번 순회하는 O(N) 만큼의 시간이 추가적으로 소요됩니다. 공간 복잡도는 O(1)로, 별도의 추가적인 데이터 구성을 필요로 하지 않습니다.

결론

이와 같이 알고리즘 문제에 대해 접근하고 해결하는 방법을 익히는 것은 코딩테스트 준비에 매우 유용합니다. 실전에서 이러한 문제를 자주 접할 수 있으므로, 다양한 문제를 풀어 보는 것이 중요합니다. “블루레이 만들기”는 자바의 기본 문법과 알고리즘 설계 능력을 동시에 요구하기 때문에 연습하기 좋은 문제입니다.

다음 강좌에서는 더욱 복잡한 알고리즘 문제를 다루며, 실전 코딩테스트에서 마주칠 수 있는 다양한 질문에 대한 해답을 제시하도록 하겠습니다. 고맙습니다!

자바 코딩테스트 강좌, 빌딩 순서 구하기

본 글에서는 자바 코딩테스트를 대비하기 위한 알고리즘 문제를 하나 풀어보겠습니다. 주제는 “빌딩 순서 구하기”입니다. 이 문제는 다양한 분야에서 활용될 수 있는 그래프 탐색 알고리즘과 정렬 알고리즘을 결합한 문제입니다. 문제를 해결하기 위해 필요한 이론적 배경 및 코드 구현 방법에 대해 자세히 설명하겠습니다.

문제 설명

당신은 도시의 여러 빌딩을 건설할 계획을 세우고 있습니다. 각 빌딩은 서로의 의존성에 따라 순서를 가지고 있습니다. 즉, 빌딩 A가 빌딩 B보다 먼저 건설되어야 하는 경우, A -> B로 의존성이 나타납니다. 이러한 규칙에 따라 모든 빌딩의 건설 순서를 정하는 문제를 해결해야 합니다.

다음은 입력으로 주어지는 빌딩의 개수 N과 의존성 정보입니다. 당신은 모든 빌딩의 건설 순서를 출력해야 합니다.
예를 들어, 다음과 같은 의존성이 주어졌다고 가정해봅시다:

            5 4
            2 1
            3 1
            4 2
            5 3
            

이 입력은 5개의 빌딩이 있으며, 다음과 같은 의존성이 존재함을 의미합니다.
1번 빌딩은 2번 빌딩이 먼저 건설되어야 하고, 1번은 3번, 2번은 4번, 3번은 5번이 먼저 건설되어야 합니다.
이 경우, 가능한 한 빌딩들의 건설 순서는 다음과 같습니다:

            1, 2, 3, 4, 5 또는 1, 2, 3, 5, 4 등.
            

문제 해결을 위한 전략

이 문제를 해결하기 위해서는 그래프 이론에서의 위상 정렬(Topological Sorting) 개념을 활용할 수 있습니다. 위상 정렬은 방향 그래프에서 모든 정점(노드)을 유향 간선의 방향에 따라 나열하는 것입니다. 이때, 간선 A -> B가 있을 경우 A는 B보다 앞에 나와야 합니다.

알고리즘의 주요 단계는 다음과 같습니다:

  1. 그래프를 인접 리스트 형태로 구현합니다.
  2. 각 노드의 진입 차수(in-degree)를 계산합니다.
  3. 진입 차수가 0인 노드를 시작으로 큐에 추가합니다.
  4. 큐에서 노드를 하나씩 꺼내며 순서를 기록하고, 그 노드에 연결된 다른 노드의 진입 차수를 감소시킵니다. 이때, 진입 차수가 0이 된 노드는 다시 큐에 추가합니다.
  5. 모든 노드가 처리될 때까지 반복합니다.

자바 구현 코드

위에서 설명한 알고리즘을 바탕으로 자바로 코드를 구현해보겠습니다. 아래는 위상 정렬을 수행하는 자바 코드입니다.

                
public class BuildingOrder {
    import java.util.*;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 빌딩과 의존성을 입력 받기
        int N = scanner.nextInt(); // 빌딩의 수
        int M = scanner.nextInt(); // 의존성의 수
        
        List> graph = new ArrayList<>();
        int[] inDegree = new int[N + 1]; // 진입 차수
        
        for (int i = 0; i <= N; i++) {
            graph.add(new ArrayList<>());
        }
        
        for (int i = 0; i < M; i++) {
            int a = scanner.nextInt();
            int b = scanner.nextInt();
            graph.get(a).add(b);
            inDegree[b]++;
        }
        
        // 위상 정렬을 수행하기 위해 과정 구현
        StringBuilder result = new StringBuilder();
        Queue queue = new LinkedList<>();

        // 진입 차수가 0인 노드 큐에 추가
        for (int i = 1; i <= N; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }
        
        while (!queue.isEmpty()) {
            int current = queue.poll();
            result.append(current).append(" ");

            for (int neighbor : graph.get(current)) {
                inDegree[neighbor]--;
                if (inDegree[neighbor] == 0) {
                    queue.offer(neighbor);
                }
            }
        }

        // 결과 출력
        System.out.println("빌딩 건설 순서: ");
        System.out.println(result.toString().trim());
        scanner.close();
    }
}
                
            

위 코드는 먼저 빌딩의 개수와 의존성을 입력받고, 이를 기반으로 그래프와 진입 차수를 초기화합니다. 그 후, 위상 정렬을 통해 건설 순서를 결정하고 출력합니다.

입출력 예제

예제 입력

            5 4
            2 1
            3 1
            4 2
            5 3
            

예제 출력

            빌딩 건설 순서: 
            1 2 3 4 5 또는 1 2 3 5 4
            

심화 학습

위상 정렬 알고리즘은 많은 실제 상황에서 사용될 수 있습니다. 예를 들어, 프로젝트 일정 관리, 컴파일러의 문법 분석, 그리고 여러 과정의 선후 관계가 있는 문제를 해결하는 데 유용합니다. 이러한 알고리즘을 이해하고 잘 활용한다면, 코딩 테스트는 물론 다양한 분야에서의 문제 해결에도 큰 도움이 될 것입니다.

연습 문제:

1. 위상 정렬을 사용하여 다음과 같은 그래프에 대한 건설 순서를 구해보세요.

2. 다음의 의존성을 구현하고, 그래프를 시각화하여 어떤 문제가 발생할 수 있는지 고민해보세요.

본 글에서 다룬 빌딩 순서 구하기 문제는 자바 프로그래밍 및 알고리즘에 대한 이해도를 높이고, 이를 실제 상황에 적용하는 데 큰 도움이 될 것입니다. 코딩 테스트에서의 성공적인 결과를 기원합니다.