기타/코딩테스트 공부

[필수 알고리즘] DFS

나는야 개발자 2025. 5. 3. 11:46
반응형

DFS란?

- 바로가기

 

[필수 알고리즘] 그래프 탐색

그래프 탐색이란?- 어떤 것들이 연속해서 이어질때, 모두 확인하는 방법- Graph: Vertex(어떤 것) + Edge(이어지는 것) 그래프 탐색 종류- BFS : 너비 우선 탐색- DFS : 깊이 우선 탐색 BFS- 자기 자식을 우선

lhy-info.tistory.com

- Stack과 재귀함수를 이용해 풀수 있음

- 그래프 탐색은 BFS로 대부분 풀수 있으며, DFS는 재귀 함수를 사용하기 위함이며 백트래킹에서 효율적이라함

 

재귀함수란?

- 자기 자신을 다시 호출하는 함수

- DFS, 백트래킹에서 주로 사용

 

풀이방법

- 시작 Vertex 찾기

- 연결된 Vertex를 계속 찾음(끝날때 까지)

- 더이상 연결된 Vertex 없을 경우 다음 진행

- 1 -> 2 -> 3 -> 4 -> 6 -> 5

 

시간 복잡도

- O(V+E)

 

자료구조

- 검색할 그래프 : 2차원배열

- 방문여부 확인 : 2차원 배열(재방문 금지)

 

문제풀이

- 백준 2667

 

1. 

public class num_2667
{
    static int[] dy = { 0, 1, 0, -1 };
    static int[] dx = { 1, 0, -1, 0 };
    public static void Main()
    {
        int n = Convert.ToInt32(Console.ReadLine());
        int[][] arr = new int[n][];
        bool[][] chk = new bool[n][];

        List<int> result = new List<int>();

        for (int i = 0; i < n; i++)
        {
            string line = Console.ReadLine();
            arr[i] = new int[n];
            for (int j = 0; j < n; j++)
            {
                // 문자열을 한 글자씩 숫자로 변환
                arr[i][j] = line[j] - '0';
            }
            chk[i] = new bool[n];
        }
    }
}

- 이전 BFS와 동일하게 dy, dx를 미리 정의 해주고 arr, chk를 각각 정의해준 후 값을 받아온다.

- "int n = Convert.ToInt32(Console.ReadLine());"로 값을 받아오니 앞글자 0이 공백으로 표기되어 받는 방식을 문자열 한글자씩 받아오도록 변경

 

2. 

static int Each = 0;

for (int i = 0; i < n; i++)
{
    for (int j = 0; j < n; j++)
    {
        if (arr[i][j] == 1 && !chk[i][j])
        {
            //방문 체크 표시
            chk[i][j] = true;
            //DFS로 크기 구하기
            Each = 0;
            Dfs(i, j, n, arr, chk);
            //값 저장 
            result.Add(Each);
        }
    }
}

static void Dfs(int i, int j, int n, int[][] arr, bool[][] chk)
{
    Each++;
    for (int x = 0; x < 4; x++)
    {
        int ny = i + dy[x];
        int nx = j + dx[x];

        if (0 <= ny && ny < n && 0 <= nx && nx < n)
        {
            if (arr[ny][nx] == 1 && !chk[ny][nx])
            {
                chk[ny][nx] = true;
                Dfs(ny, nx, n, arr, chk);
            }
        }
    }
}

- 2중 for문을 이용해 1인지 false인지 체크

- "static int Each = 0;" 전역변수로 선언해 준 후 Dfs가 실행될때마다 +1 증가

 

3.

result.Sort();
Console.WriteLine(result.Count);
for (int i = 0; i < result.Count; i++)
{
    Console.WriteLine(result[i]);
}

- 문제에 맞게 정렬 후 결과 출력

 

최종코드

/*
1. 아이디어
- 2중 for, 값이 1&& 방문X => DFS
- DFS를 통해 찾은 값을 저장 후 출력
2. 시간 복잡도
- DFS : O(V+E)
- V, E : N^2, 4N^2
- V + E : 5N^2 ~= N^2 ~ = 625 >> 가능
3. 자료구조
- 그래프 저장 : int[][]
- 방문여부 : bool[][]
- 결과값 : int[]
*/

public class num_2667
{
    static int[] dy = { 0, 1, 0, -1 };
    static int[] dx = { 1, 0, -1, 0 };
    static int Each = 0;
    public static void Main()
    {
        int n = Convert.ToInt32(Console.ReadLine());
        int[][] arr = new int[n][];
        bool[][] chk = new bool[n][];

        List<int> result = new List<int>();

        for (int i = 0; i < n; i++)
        {
            string line = Console.ReadLine();
            arr[i] = new int[n];
            for (int j = 0; j < n; j++)
            {
                // 문자열을 한 글자씩 숫자로 변환
                arr[i][j] = line[j] - '0';
            }
            chk[i] = new bool[n];
        }

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (arr[i][j] == 1 && !chk[i][j])
                {
                    //방문 체크 표시
                    chk[i][j] = true;
                    //DFS로 크기 구하기
                    Each = 0;
                    Dfs(i, j, n, arr, chk);
                    //값 저장 
                    result.Add(Each);
                }
            }
        }

        result.Sort();
        Console.WriteLine(result.Count);
        for (int i = 0; i < result.Count; i++)
        {
            Console.WriteLine(result[i]);
        }
    }

    static void Dfs(int i, int j, int n, int[][] arr, bool[][] chk)
    {
        Each++;
        for (int x = 0; x < 4; x++)
        {
            int ny = i + dy[x];
            int nx = j + dx[x];

            if (0 <= ny && ny < n && 0 <= nx && nx < n)
            {
                if (arr[ny][nx] == 1 && !chk[ny][nx])
                {
                    chk[ny][nx] = true;
                    Dfs(ny, nx, n, arr, chk);
                }
            }
        }
    }
}

 

참고영상

- 바로가기

 

반응형

'기타 > 코딩테스트 공부' 카테고리의 다른 글

[필수 알고리즘] 시뮬레이션  (0) 2025.05.03
[필수 알고리즘] 백 트래킹  (0) 2025.05.03
[필수 알고리즘] BFS  (0) 2025.05.03
[필수 알고리즘] 그래프 탐색  (0) 2025.05.03
[백준] 블랙잭 - 2798번  (0) 2025.05.02