๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์•Œ๊ณ ๋ฆฌ์ฆ˜

Topological Sort๋ž€? Kahn's Algorithm์œผ๋กœ DAG ์ •๋ ฌ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ธฐ

by Marco Backman 2025. 6. 1.

๐Ÿง  DAG๋ž€?

DAG(Directed Acyclic Graph)๋Š” ์‚ฌ์ดํด์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์ž…๋‹ˆ๋‹ค. ์ด ๊ตฌ์กฐ๋Š” ์ด๋ฒคํŠธ ๊ฐ„์˜ ์„ ํ›„ ๊ด€๊ณ„๋ฅผ ํŒŒ์•…ํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ์—์„œ ๋งค์šฐ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ณผ๋ชฉ ์ˆ˜๊ฐ• ์ˆœ์„œ๋ฅผ ์ •ํ•˜๋Š” ๋ฌธ์ œ์—์„œ ํ•„์ˆ˜ ์„ ์ด์ˆ˜ ๊ณผ๋ชฉ์ด ์žˆ๋‹ค๋ฉด ๊ทธ ๊ด€๊ณ„๋ฅผ DAG๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋Œ€ํ‘œ ๋ฌธ์ œ: LeetCode - Course Schedule II

 

 

โœ… ๋น„์ˆœํ™˜ ๊ทธ๋ž˜ํ”„

DAG ๋ฅผ ๋งŒ์กฑํ•˜๋Š” ๋น„์ˆœํ™˜ ๊ทธ๋ž˜ํ”„

 

 

โŒ ์ˆœํ™˜ ๊ทธ๋ž˜ํ”„

DAG๋ฅผ ์œ„๋ฐ˜ํ•˜๋Š” ์ˆœํ™˜ ๊ทธ๋ž˜ํ”„ - ์‚ฌ์ดํด์ด ์กด์žฌํ•œ๋‹ค

 

์œ„์ƒ ์ •๋ ฌ(Topological Sort)์ด๋ž€?

์ •์˜: DAG(Directed Acyclic Graph)์˜ ๋…ธ๋“œ๋ฅผ ์„ ํ˜•(linear) ์ˆœ์„œ๋กœ ๋‚˜์—ดํ•˜๋Š” ์ •๋ ฌ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

์ •๋ ฌ๋œ ๊ฒฐ๊ณผ๋Š” ๋ชจ๋“  ๊ฐ„์„  (a → b)์— ๋Œ€ํ•ด a๊ฐ€ b๋ณด๋‹ค ์•ž์„œ๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, ๊ทธ๋ž˜ํ”„์— ์‚ฌ์ดํด์ด ์žˆ๋‹ค๋ฉด ์œ„์ƒ ์ •๋ ฌ์€ ์ˆ˜ํ–‰๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
์ด๋ฅผ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด ์ผ๋ฐ˜์ ์œผ๋กœ DFS ๋˜๋Š” BFS(Kahn’s Algorithm) ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

 

๐Ÿ› ๏ธ ๊ตฌํ˜„ ๋ฐฉ๋ฒ• (BFS - Kahn's Algorithm)

 

  • ํ•„์ˆ˜ ๊ตฌ์„ฑ ์š”์†Œ:
    1. in-degree ๋ฐฐ์—ด: ๊ฐ ๋…ธ๋“œ์— ๋“ค์–ด์˜ค๋Š” ๊ฐ„์„  ์ˆ˜ ์ €์žฅ
    2. ๊ทธ๋ž˜ํ”„ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ: ๊ฐ ๋…ธ๋“œ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ
    3. Queue: in-degree๊ฐ€ 0์ธ ๋…ธ๋“œ๋ฅผ ์ฒ˜๋ฆฌ
    4. ๊ฒฐ๊ณผ ๋ฆฌ์ŠคํŠธ: ์œ„์ƒ ์ •๋ ฌ๋œ ๋…ธ๋“œ ์ €์žฅ
  • ์ „์ฒด ๊ณผ์ •:
    1. ๋ชจ๋“  ๋…ธ๋“œ์˜ in-degree ๊ณ„์‚ฐ
    2. in-degree๊ฐ€ 0์ธ ๋…ธ๋“œ๋“ค์„ Queue์— ์‚ฝ์ž…
    3. Queue์—์„œ ๋…ธ๋“œ๋ฅผ ํ•˜๋‚˜์”ฉ ๊บผ๋‚ด๊ณ :
      • ๊ฒฐ๊ณผ ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€
      • ํ•ด๋‹น ๋…ธ๋“œ์—์„œ ์ด์–ด์ง€๋Š” ๊ฐ„์„  ์ œ๊ฑฐ (in-degree ๊ฐ์†Œ)
      • in-degree๊ฐ€ 0์ด ๋œ ๋…ธ๋“œ๋ฅผ Queue์— ์ถ”๊ฐ€
    4. ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ–ˆ์„ ๋•Œ ๊ฒฐ๊ณผ ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ๊ฐ€ ์ „์ฒด ๋…ธ๋“œ ์ˆ˜์™€ ๊ฐ™๋‹ค๋ฉด ์„ฑ๊ณต์ ์ธ ์œ„์ƒ ์ •๋ ฌ, ์•„๋‹ˆ๋ผ๋ฉด ์‚ฌ์ดํด ์กด์žฌ

์•„๋ž˜๋Š” ์˜ˆ์‹œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

class Solution {

    public int[] findOrder(int numCourses, int[][] prerequisites) {
        // Create adjacency list for graph representation
        List<Integer>[] courseSet = new ArrayList[numCourses];
        int[] inDegree = new int[numCourses]; // Track the in-degrees (number of incoming edges)

        // Build the graph
        for (int i = 0; i < prerequisites.length; i++) {
            int course = prerequisites[i][0];
            int prereq = prerequisites[i][1];

            if (courseSet[prereq] == null) {
                courseSet[prereq] = new ArrayList<>();
            }

            // Add an edge from prereq to course (correct direction)
            courseSet[prereq].add(course);
            inDegree[course]++; // Increment the in-degree of the course
        }
        
        Queue<Integer> queue = new LinkedList<>(); //Look for starting node
        for (int i = 0; i < numCourses; i++) {
            if (inDegree[i] == 0) {
                queue.add(i);
            }
        }

        int[] result = new int[numCourses];
        int index = 0;

        while (!queue.isEmpty()) {
            Integer courseNum = queue.poll(); //start
            result[index++] = courseNum; //append result

            //Now, get the next course
            if (courseSet[courseNum] != null) {
                List<Integer> nextCourses = courseSet[courseNum];
                for (Integer nextCourse : nextCourses) {
                    inDegree[nextCourse]--; //reduce indegree count if visited
                    if (inDegree[nextCourse] == 0) {
                        queue.add(nextCourse);
                    }
                }
            }
        }

        // Check if topological sort was possible, if incremented index is same as provided numCourses
        return index == numCourses ? result : new int[0];
    }
}

 

โฑ๏ธ ์‹œ๊ฐ„ ๋ณต์žก๋„ ๋ถ„์„

  • ์‹œ๊ฐ„ ๋ณต์žก๋„: O(V + E)
    • V: ๋…ธ๋“œ ์ˆ˜ (numCourses)
    • E: ๊ฐ„์„  ์ˆ˜ (prerequisites.length)
  • ๊ณต๊ฐ„ ๋ณต์žก๋„: O(V + E)
    • ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ ๋ฐ in-degree ๋ฐฐ์—ด ์ €์žฅ ๊ณต๊ฐ„


โœ… ๋งˆ๋ฌด๋ฆฌ ์š”์•ฝ

  • DAG๋Š” ์‚ฌ์ดํด์ด ์—†๋Š” ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์ด๋ฉฐ, ์„ ํ›„ ๊ด€๊ณ„๊ฐ€ ํ•„์š”ํ•œ ๋ฌธ์ œ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • ์œ„์ƒ ์ •๋ ฌ์€ DAG์˜ ์ •์ ์„ ์„ ํ˜•์œผ๋กœ ๋‚˜์—ดํ•˜๋Š” ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค
  • Kahn’s Algorithm์€ BFS ๊ธฐ๋ฐ˜์˜ ์œ„์ƒ ์ •๋ ฌ๋กœ, ์‚ฌ์ดํด ํƒ์ง€์—๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค