코틀린 코딩테스트 강좌, 그래프의 표현

안녕하세요! 오늘은 코틀린을 사용하여 코딩테스트에서 자주 나오는 그래프의 표현 방법에 대해 자세히 알아보겠습니다. 그래프는 여러 분야에서 꽤 중요한 자료구조로, 다양한 문제를 해결할 때 필수적인 근본기능을 가지고 있습니다. 이번 글에서는 그래프를 어떻게 표현하고, 그 표현을 사용하여 문제를 해결하는 방법을 설명하겠습니다.

그래프란 무엇인가?

그래프는 노드(정점)와 엣지(간선)로 구성된 자료구조입니다. 노드는 객체를 나타내며, 엣지는 노드 간의 관계를 나타냅니다. 그래프는 방향성에 따라 방향 그래프와 무향 그래프로 나눌 수 있으며, 가중치 여부에 따라 가중 그래프와 비가중 그래프로 나눌 수 있습니다.

그래프의 표현 방법

그래프는 다양한 방법으로 표현할 수 있으며, 가장 흔한 두 가지 방법은 인접 행렬(Adjacency Matrix)과 인접 리스트(Adjacency List)가 있습니다.

1. 인접 행렬

인접 행렬은 N x N 크기의 2차원 배열을 사용하여 그래프를 표현하는 방법입니다. N은 그래프의 노드 수이며, 행렬의 각 요소는 노드 간의 연결 여부를 나타냅니다. 예를 들어, 노드 A와 노드 B가 연결되어 있다면, matrix[A][B]는 1이 됩니다.

    fun createAdjacencyMatrix(vertices: Int, edges: List>): Array> {
        val matrix = Array(vertices) { Array(vertices) { 0 } }
        for (edge in edges) {
            val (from, to) = edge
            matrix[from][to] = 1
            matrix[to][from] = 1  // 무향 그래프의 경우
        }
        return matrix
    }
    

2. 인접 리스트

인접 리스트는 각 노드에 대해 연결된 노드를 저장하는 리스트를 사용하는 방법입니다. 이 방식은 메모리 사용 면에서 효율적이며, 노드 수가 적거나 간선 수가 적은 그래프에서 유리합니다.

    fun createAdjacencyList(vertices: Int, edges: List>): List> {
        val list = MutableList(vertices) { mutableListOf() }
        for (edge in edges) {
            val (from, to) = edge
            list[from].add(to)
            list[to].add(from)  // 무향 그래프의 경우
        }
        return list
    }
    

문제: 친구 관계 네트워크

다음은 친구 관계를 나타내는 그래프의 문제입니다.

문제: N명의 사람과 그들 사이의 친구 관계가 주어질 때, 두 사람 사이의 친구 관계가 존재하는지 확인하는 프로그램을 작성하시오. 친구 관계는 무향 그래프로 표현된다. 단, 두 사람의 번호는 0부터 N-1까지 연속적으로 주어진다.

문제 해결 과정

1. 입력 형식 이해

먼저 주어지는 데이터를 이해해야 합니다. 입력은 다음과 같습니다:

  • 첫 번째 줄에 사람의 수 N이 주어진다.
  • 두 번째 줄에 친구 관계의 수 M이 주어진다.
  • 이후 M개의 줄에 걸쳐 각 친구 관계를 나타내는 두 정수 a, b가 주어진다.

2. 데이터 구조 선택

주어진 친구 관계를 저장하기 위해 인접 리스트를 사용합니다. 이렇게 하면 친구 관계를 쉽게 탐색할 수 있습니다.

3. 그래프 생성

    fun main() {
        val reader = BufferedReader(InputStreamReader(System.`in`))
        val n = reader.readLine().toInt()
        val m = reader.readLine().toInt()

        val edges = mutableListOf>()
        for (i in 0 until m) {
            val (a, b) = reader.readLine().split(" ").map { it.toInt() }
            edges.add(Pair(a, b))
        }

        val adjacencyList = createAdjacencyList(n, edges)
    }
    

4. 친구 관계 확인

특정 두 사람의 친구 관계를 확인하는 방법은 DFS(Depth First Search) 또는 BFS(Breadth First Search)를 사용하여 연결 여부를 체크하는 것입니다. 여기서는 DFS를 사용하여 구현해 보겠습니다.

    fun isConnected(adjList: List>, start: Int, target: Int, visited: BooleanArray): Boolean {
        if (start == target) return true
        visited[start] = true
        
        for (neighbor in adjList[start]) {
            if (!visited[neighbor]) {
                if (isConnected(adjList, neighbor, target, visited)) {
                    return true
                }
            }
        }
        return false
    }

    fun main() {
        // 이전 코드와 이어서
        val query = reader.readLine().split(" ").map { it.toInt() }
        val (x, y) = query

        val visited = BooleanArray(n) { false }
        val result = isConnected(adjacencyList, x, y, visited)
        println(if (result) "YES" else "NO")
    }
    

결론

이번 강좌에서는 그래프의 기본 개념 및 표현 방법, 그리고 이를 활용하여 친구 관계 네트워크 문제를 해결하는 방법에 대해 알아보았습니다. 그래프는 다양한 문제를 해결하는 데 필수적이며, 알고리즘 테스트에서 이러한 그래프 표현 및 탐색 기술은 매우 유용합니다.

코틀린을 사용하여 예제를 구현해 보았으니, 직접 다양한 그래프 문제를 풀어보며 연습해보시기 바랍니다. 다음 시간에는 BFS와 DFS의 차이점과 이를 활용한 다양한 문제 해결 전략에 대해 다뤄보겠습니다. 여러분의 학습 여정에 도움이 되기를 바랍니다!

작성자: 조광형

날짜: 2024년 11월 26일

코틀린 코딩테스트 강좌, 구간 합 구하기 3

안녕하세요! 오늘은 코틀린을 이용한 코딩테스트 문제 중 “구간 합 구하기 3″에 대해 다뤄보겠습니다. 이 문제는 주어진 배열의 특정 구간에 대한 합을 효율적으로 계산해야 하는 문제입니다. 특히, 반복적으로 구간 합을 계산해야 할 때, 이러한 효율적인 알고리즘이 매우 중요합니다.

문제 설명

여러분에게 N개의 정수로 이루어진 배열 A와 Q개의 쿼리가 주어집니다. 각 쿼리는 두 개의 정수 L과 R을 포함하고 있으며, 이는 배열 A의 L번째 인덱스부터 R번째 인덱스까지의 합을 계산하는 것입니다. 단, 배열은 1번 인덱스부터 시작합니다. 여러분은 모든 Q개의 쿼리에 대해 결과를 출력해야 합니다.

입력 형식

    첫 번째 줄: N (1 ≤ N ≤ 100,000)
    두 번째 줄: N개의 정수 (각각의 정수는 -10,000,000 ≤ A[i] ≤ 10,000,000)
    세 번째 줄: Q (1 ≤ Q ≤ 100,000)
    이후 Q개의 줄에는 각 쿼리가 L R의 형태로 주어짐.
    

출력 형식

    Q개의 각 줄에 대해 구간 합을 출력합니다.
    

접근 방법

기본적인 방법은 주어진 L과 R에 대해 직접적으로 배열을 순회하며 합을 계산하는 것입니다. 그러나 이는 시간 복잡도가 O(Q * N)으로, Q와 N이 최대 100,000일 때 최악의 경우 10억 번의 연산이 이루어질 수 있습니다. 그러므로 이것은 비효율적입니다. 이 문제는 전처리를 통해 O(1)의 시간 복잡도로 쿼리를 처리하는 방법이 필요합니다.

구간 합 구하기 문제를 해결하기 위한 효율적인 방법 중 하나는 누적 합 배열을 사용하는 것입니다. 누적 합 배열을 사용하면 특정 구간 L ~ R의 합을 쉽게 계산할 수 있습니다.

누적 합 배열

누적 합 배열 P를 정의합니다. P[i]는 배열 A의 첫 번째 원소부터 i번째 원소까지의 합을 저장합니다.

    P[i] = A[1] + A[2] + ... + A[i]
    

그러면 구간 L ~ R에 대한 합은 다음과 같이 계산할 수 있습니다:

    sum(L, R) = P[R] - P[L - 1]
    

이 방법은 O(N)으로 누적 합 배열을 구할 수 있고, 이후 각 쿼리에 대해 O(1)로 결과를 얻을 수 있습니다. 전체 시간 복잡도는 O(N + Q)가 됩니다.

코드 구현

코틀린 코드

    fun main() {
        val reader = System.`in`.bufferedReader()
        val n = reader.readLine().toInt()
        val a = reader.readLine().split(" ").map { it.toInt() }
        val q = reader.readLine().toInt()
        
        // 누적 합 배열 초기화
        val p = LongArray(n + 1)
        
        // 누적 합 계산
        for (i in 1..n) {
            p[i] = p[i - 1] + a[i - 1]
        }

        val result = StringBuilder()
        for (i in 0 until q) {
            val (l, r) = reader.readLine().split(" ").map { it.toInt() }
            // 구간 합 계산
            result.append(p[r] - p[l - 1]).append("\n")
        }

        // 결과 출력
        println(result.toString())
    }
    

코드 설명

위의 코드는 코틀린으로 작성된 “구간 합 구하기 3” 문제의 해결 방법입니다. 각각의 부분을 설명하겠습니다.

1. 입력 처리

먼저 N, A, Q 값을 입력받습니다. N은 배열의 크기를 의미하고, A는 정수 배열, Q는 주어진 쿼리의 수를 의미합니다.

2. 누적 합 배열 생성

누적 합 배열 P를 생성합니다. P[0]는 0으로 초기화되고, P[1]부터 P[n]까지 누적 합을 계산합니다. 이는 배열 A의 각 원소를 더한 결과를 저장하게 됩니다.

3. 쿼리 처리

각 쿼리에 대해 L과 R 값을 입력받아, 누적 합 배열을 이용하여 O(1) 시간 내에 구간 합을 계산합니다. 이 결과는 StringBuilder에 추가되어 마지막에 출력됩니다.

결론

“구간 합 구하기 3” 문제를 통해 누적 합 배열 활용의 중요성을 배웠습니다. 이 기법을 이용하면 대량의 데이터에서도 효율적으로 쿼리를 처리할 수 있다는 것을 알게 되었습니다. 알고리즘 문제를 풀 때는 항상 시간 복잡도를 고려하여 최적의 방법을 찾아야 합니다. 여러분의 코딩테스트 준비에 도움이 되길 바랍니다.

더 알아보기

다음 강좌에서는 더 다양한 알고리즘 문제를 다뤄보겠습니다. 계속해서 코팅 테스트를 준비하시고 많은 연습 하시길 바랍니다. 감사합니다!

코틀린 코딩테스트 강좌, 구간 합 구하기 2

코딩 테스트에서 다루어지는 여러 알고리즘 중에서 ‘구간 합’ 문제는 빈번하게 출제됩니다.
이 포스트에서는 구간 합 구하기 2라는 주제로 문제를 풀어보도록 하겠습니다.
특히 코틀린 프로그래밍 언어를 활용하여 작성할 예정입니다.

문제 설명

여러 개의 정수가 주어질 때, 특정 구간의 합을 효율적으로 계산하는 방법을 제시하는 문제입니다.
다음은 문제의 정의입니다:

정수 N과 M이 주어질 때, 
N개의 정수가 주어지며, 
M개의 질의가 주어질 것입니다. 
각 질의는 두 정수 i와 j로 구성되어 있으며, 
i와 j사이의 정수 합을 계산해야 합니다.

입력 형식:
- 첫 번째 줄에 N(1 ≤ N ≤ 100,000)과 M(1 ≤ M ≤ 100,000) 이 주어진다.
- 두 번째 줄에 N개의 정수가 주어진다. 각 정수는 1,000,000을 넘지 않는다.
- 이어지는 M개의 줄에 걸쳐 i와 j가 주어진다. (1 ≤ i ≤ j ≤ N)

출력 형식:
- 각 질의에 대해, i번째 수부터 j번째 수까지의 합을 출력합니다.

문제 해결 과정

이 문제를 해결하기 위해서는 효율적인 알고리즘이 필요합니다. 단순히 각 질의에 대해 루프를 돌며 합을 계산하는 것은 O(N*M)의 시간 복잡도를 가지게 되어, 입력값이 큰 경우에는 시간 초과로 실패할 수 있습니다.

1. 누적 합 배열 사용하기

체크하는 관점에서 모든 합을 매번 계산하는 대신, 누적 합 배열을 사용하는 방법이 있습니다. 누적 합 배열을 활용하면, 특정 구간의 합을 O(1)의 시간 복잡도로 구할 수 있습니다.

누적 합 배열 prefixSum를 정의하면, prefixSum[k]는 배열의 처음부터 k번째 수까지의 합을 나타냅니다.
따라서 다음과 같은 관계를 가집니다:

prefixSum[k] = prefixSum[k-1] + array[k-1] (1 ≤ k ≤ N)

이때, 특정 구간의 합은 다음과 같이 구할 수 있습니다:

sum(i, j) = prefixSum[j] - prefixSum[i-1]

2. 알고리즘 구현하기

이제 이러한 아이디어를 토대로 코드를 구현해 보겠습니다.
다음의 코드는 코틀린을 사용하여 문제를 풀이하는 예제입니다:


fun main() {
    val (n, m) = readLine()!!.split(" ").map { it.toInt() }
    val numbers = readLine()!!.split(" ").map { it.toInt() }.toIntArray()
    val prefixSum = LongArray(n + 1)

    for (i in 1..n) {
        prefixSum[i] = prefixSum[i - 1] + numbers[i - 1].toLong()
    }

    for (j in 0 until m) {
        val (i, j) = readLine()!!.split(" ").map { it.toInt() }
        println(prefixSum[j] - prefixSum[i - 1])
    }
}

3. 코드 설명

위 코드를 통해 어떤 방식으로 구간 합을 구하는지 설명하겠습니다:

  • val (n, m) = readLine()!!.split(" ").map { it.toInt() }:
    첫 번째 줄에서 N과 M을 입력받습니다.
  • val numbers = readLine()!!.split(" ").map { it.toInt() }.toIntArray():
    두 번째 줄에서 N개의 정수를 입력받고 배열로 변환합니다.
  • val prefixSum = LongArray(n + 1):
    누적 합을 저장할 배열을 생성합니다. (0번째 인덱스는 0으로 초기화)
  • for (i in 1..n):
    반복문을 사용하여 누적 합을 계산합니다. prefixSum[i]에 i번째 수까지의 합을 저장합니다.
  • for (j in 0 until m):
    각 질의에 대해 입력을 받아 구간 합을 계산합니다.
  • println(prefixSum[j] - prefixSum[i - 1]):
    i번째 인덱스부터 j번째 인덱스까지의 합을 출력합니다.

복잡도 분석

위 코드의 시간 복잡도는 다음과 같습니다:

  • 누적 합 배열을 생성하는 과정: O(N)
  • M개의 질의에 대해 각각 O(1)로 구간 합을 구하는 과정: O(M)

따라서 전체 시간 복잡도는 O(N + M)입니다. 이는 주어진 문제의 구간 합을 효과적으로 처리할 수 있는 좋은 방법입니다.

결론

이번 강좌에서는 구간 합 구하기 2라는 문제를 통해 누적 합을 사용하여 효율적으로 문제를 풀어보았습니다.
이와 같은 방식은 많은 알고리즘 문제에서 유용하게 활용될 수 있으니, 다양한 문제에 적용해 보시기 바랍니다.

우리는 여러 개의 정수로 이루어진 배열에서 특정 구간의 합을 빠르고 효율적으로 계산하는 문제를 다루었습니다.
코틀린의 배열, 리스트와 같은 자료구조를 이용하여 다양한 알고리즘 문제를 해결할 수 있다는 것을 알 수 있었습니다.

추가 연습 문제

아래의 문제들을 추가로 연습해보시기 바랍니다:

  • 다양한 질의 형태에서의 구간 최소값, 최대값 구하기
  • 이상한 구간 합 구하기: 특정 조건을 만족하는 구간만 합산하기
  • 다차원 배열의 구간 합 구하기

이 포스트가 여러분의 코딩 테스트 준비에 도움이 되길 바랍니다.
감사합니다!

코틀린 코딩테스트 강좌, 구간 합 구하기 1

안녕하세요! 이번 포스트에서는 코틀린으로 구간 합 구하기 문제를 해결하는 방법에 대해 자세히 알아보도록 하겠습니다.
구간 합 문제는 프로그래밍 대회나 코딩 테스트에서 자주 출제되는 유형이며, 이를 효율적으로 해결하는 방법을 알고 있다면
여러 문제를 빠르게 풀 수 있는 능력을 키울 수 있습니다.

문제 설명

배열이 주어졌을 때, 특정 구간의 합을 구하는 문제입니다. 주어진 배열과 여러 쿼리에 대해
각 구간의 합을 구하는 문제를 해결하는 것입니다. 예를 들어, 배열 A가 다음과 같다고 가정합니다:

        A = [10, 20, 30, 40, 50]
    

이때 사용자가 원하는 구간 (i, j)에서의 합을 구하는 쿼리 쿼리를 받았을 때,
그에 대한 합을 반환해야 합니다.

입력 형식

첫 번째 줄에는 배열의 크기 N과 쿼리의 개수 M이 주어집니다.
그 다음 N개의 정수가 주어져 배열 A를 구성합니다.
다음 M개의 줄에는 각 줄마다 두 개의 정수 ij가 주어지고,
이는 구간 A[i]부터 A[j]까지의 합을 구하는 쿼리를 의미합니다.

출력 형식

각 쿼리에 대한 구간의 합을 출력합니다.

예제 입력

    5 3
    10 20 30 40 50
    1 3
    2 4
    1 5
    

예제 출력

    60
    90
    150
    

문제 풀이 접근

이 문제를 해결하기 위해서는 두 가지 방법이 있습니다.
첫 번째는 단순히 매 쿼리에 대해 반복문을 돌면서 합을 구하는 것이고,
두 번째는 구간 합 배열을 활용하는 것입니다.
두 번째 방법이 훨씬 더 효율적이므로 이를 중심으로 설명하겠습니다.

구간 합 배열

구간 합 배열을 이용하면 쿼리 1개당 O(1) 시간복잡도로 구간 합을 구할 수 있습니다.
구간 합 배열을 계산하는 시간이 O(N)이므로,
총 시간복잡도는 O(N + M)입니다.
이는 쿼리의 개수가 많을수록 더 효율적입니다.

구간 합 배열의 정의

구간 합 배열은 주어진 배열의 접두사 합을 저장하는 배열입니다.
즉, 배열 A의 i번째 인덱스까지의 합을 저장하는 배열 S를 정의합니다.
S[i] = A[0] + A[1] + ... + A[i-1]와 같습니다.

구간 합 계산 방법

구간 A[i]부터 A[j]까지의 합은 다음과 같이 구할 수 있습니다:
sum = S[j+1] - S[i]

여기서 S[j+1]A[0]부터 A[j]까지의 합이고,
S[i]A[0]부터 A[i-1]까지의 합입니다.
따라서 S[j+1]에서 S[i]를 빼면 A[i]부터 A[j]까지의 합이 됩니다.

코드 구현

이제 코틀린을 이용하여 이 문제를 해결하는 코드를 작성해 보겠습니다.

코틀린 코드

    fun main() {
        val (n, m) = readLine()!!.split(" ").map { it.toInt() }
        val a = readLine()!!.split(" ").map { it.toInt() }
        
        val s = IntArray(n + 1)
        
        for (i in 1..n) {
            s[i] = s[i - 1] + a[i - 1]
        }
        
        repeat(m) {
            val (i, j) = readLine()!!.split(" ").map { it.toInt() }
            println(s[j] - s[i - 1])
        }
    }
    

코드 설명

1. 첫 줄에서 NM을 입력받습니다.
2. 두 번째 줄에서 배열 A를 입력받습니다.
3. 구간 합 배열 S를 초기화합니다. 크기는 N + 1입니다.
4. 반복문을 통해 구간 합 배열 S를 계산합니다.
5. 쿼리에 대해 반복하며 각 구간의 합을 계산하고 출력합니다.

결론

구간 합 구하기 문제는 다양한 문제에 응용될 수 있는 유용한 기법입니다.
코틀린을 이용하여 구간 합 배열을 사용하면 훨씬 빠르게 문제를 해결할 수 있습니다.
이 강좌를 통해 여러분들이 구간 합 구하기 문제에 대한 이해를 높이고,
코딩 테스트에서 유용하게 활용할 수 있기를 바랍니다.

다음 포스트에서는 구간 합을 확장하여 다른 유형의 문제를 다뤄보도록 하겠습니다.
계속해서 학습을 지속하세요!

코틀린 코딩테스트 강좌, 구간 합

1. 서론

안녕하세요. 이번 시간에는 코틀린으로 구간 합을 효율적으로 구하는 방법에 대해 알아보겠습니다.
코딩테스트에서 자주 등장하는 문제 중 하나로, 주어진 수열의 특정 구간에 대한 합을 구하는 문제입니다.
이 과정을 통해 구간 합을 해결하기 위한 다양한 방법과 그에 따른 시간 복잡도에 대해 논의하도록 하겠습니다.

2. 문제 설명

주어진 수열 A와 쿼리 Q가 있을 때, 각 쿼리는 두 정수 LR로 주어집니다.
우리는 L부터 R까지의 합을 빠르게 구해야 합니다.

입력

  • 첫 번째 줄에는 수열의 크기 N과 쿼리의 개수 M이 주어집니다.
  • 두 번째 줄에는 N개의 정수가 주어져 수열 A를 이룹니다.
  • 다음 M개의 줄마다 LR이 주어집니다.

출력

각 쿼리에 대한 결과를 한 줄에 하나씩 출력합니다.

제한

  • 1 ≤ N ≤ 100,000
  • 1 ≤ M ≤ 100,000
  • -1,000,000,000 ≤ A[i] ≤ 1,000,000,000

3. 접근 방법

구간 합을 구하는 여러 가지 방법이 있지만, 기본적인 접근 방법은 다음 두 가지입니다.

3.1. 단순 반복

가장 직관적인 방법은, 각 쿼리에 대해 정의된 범위에서 직접 합을 계산하는 것입니다. 하지만 이 방법은 시간 복잡도가 O(N)이고, 최대 쿼리가 100,000개일 경우 최악의 경우 O(N * M) = O(10^10)로 매우 비효율적입니다.

3.2. 누적 합 배열(Cumulative Sum Array)

아래의 방법론을 사용하여 효율적으로 구간 합을 계산할 수 있습니다.

누적 합 배열은 특정 위치까지의 합을 미리 계산해 두는 배열로, 선형 시간 O(N)으로 배열을 만듭니다.
이렇게 하면 각 쿼리를 O(1)로 처리할 수 있게 됩니다. 따라서 전체 시간 복잡도는 O(N + M)입니다.

4. 구현

누적 합 배열을 사용한 구간 합 계산 알고리즘을 코틀린으로 구현해 보겠습니다.


fun main() {
    val reader = System.`in`.bufferedReader()
    val (n, m) = reader.readLine().split(" ").map { it.toInt() }

    val array = reader.readLine().split(" ").map { it.toInt() }.toIntArray()
    val sumArray = IntArray(n + 1)

    // 누적 합 배열 생성
    for (i in 1..n) {
        sumArray[i] = sumArray[i - 1] + array[i - 1]
    }

    val result = StringBuilder()
    // 쿼리 처리
    repeat(m) {
        val (l, r) = reader.readLine().split(" ").map { it.toInt() }
        val sum = sumArray[r] - sumArray[l - 1]
        result.append(sum).append("\n")
    }

    println(result)
}

            

위의 구현에서 핵심은 sumArray를 통해 각 쿼리를 O(1)로 처리할 수 있다는 점입니다.
구간 [L, R]의 합은 sumArray[R] - sumArray[L-1]로 쉽게 구할 수 있습니다.

5. 시간 복잡도 분석

이 알고리즘의 시간 복잡도를 분석해보면 다음과 같습니다.

  • 누적 합 배열을 만드는 과정: O(N)
  • 쿼리 처리: O(M)
  • 총 시간 복잡도: O(N + M)

따라서 주어진 제약 조건 하에서 우리는 효율적으로 구간 합을 계산할 수 있게 됩니다.

6. 예제

6.1. 입력 예시


5 3
1 2 3 4 5
1 3
2 5
1 5

            

6.2. 출력 예시


6
14
15

            

위 예제에서 입력으로 주어진 쿼리의 결과는 1부터 3까지의 합은 6, 2부터 5까지의 합은 14,
전체 1부터 5까지의 합은 15로 계산됩니다.

7. 결론

이번 강좌에서는 구간 합을 계산하는 다양한 방법과 그에 따른 정확한 구현을 살펴보았습니다.
특히, 누적 합 배열을 사용하여 효율적으로 구간 합을 계산하는 방법에 대해 깊이 있게 논의했습니다.
이 알고리즘은 많은 코딩 테스트 문제와 실무에서 유용하게 사용될 수 있습니다. 다음 시간에는 더 복잡한 데이터 구조와 알고리즘에 대해 알아보도록 하겠습니다.