본문 바로가기
알고리즘/프로그래머스

[프로그래머스] BFS/DFS - 네트워크

by dding-g 2020. 5. 16.

프로그래머스

📌 네트워크

📕 문제

문제 설명

네트워크란 컴퓨터 상호 간에 정보를 교환할 수 있도록 연결된 형태를 의미합니다. 예를 들어, 컴퓨터 A와 컴퓨터 B가 직접적으로 연결되어있고, 컴퓨터 B와 컴퓨터 C가 직접적으로 연결되어 있을 때 컴퓨터 A와 컴퓨터 C도 간접적으로 연결되어 정보를 교환할 수 있습니다. 따라서 컴퓨터 A, B, C는 모두 같은 네트워크 상에 있다고 할 수 있습니다.

컴퓨터의 개수 n, 연결에 대한 정보가 담긴 2차원 배열 computers가 매개변수로 주어질 때, 네트워크의 개수를 return 하도록 solution 함수를 작성하시오.

제한사항
  • 컴퓨터의 개수 n은 1 이상 200 이하인 자연수입니다.
  • 각 컴퓨터는 0부터 n-1인 정수로 표현합니다.
  • i번 컴퓨터와 j번 컴퓨터가 연결되어 있으면 computers[i][j]를 1로 표현합니다.
  • computer[i][i]는 항상 1입니다.
입출력 예
n computers return
3 [[1, 1, 0], [1, 1, 0], [0, 0, 1]] 2
3 [[1, 1, 0], [1, 1, 1], [0, 1, 1]] 1
입출력 예 설명

예제 #1
아래와 같이 2개의 네트워크가 있습니다.
image0.png

예제 #2
아래와 같이 1개의 네트워크가 있습니다.
image1.png


📒 문제 설명

DFS 문제이다. HeadNode를 시작으로 Link 된 모든 Node들은 하나의 네트워크 이고, 이걸 computer.length 까지 반복해서 모든 경우의 수를 구한다.

문제 접근은

  1. computer.length 까지 반복하되
  2. 이미 방문한 node는 검사할 필요가 없음. 하나의 네트워크로 취급되기 때문.
  3. computer.length 까지 반복하면서 link된 node? && 방문한 node? 인지를 체크하는 조건을 주면 된다.

🥕 나의 풀이

잘풀고 있다고 생각하다가 마지막에 테스트케이스 1, 4, 5, 7 번에서 막혔다. 다른분의 풀이를 봐도 나랑 비슷하게 풀고 체크하는 조건도 비슷한것 같은데 왜 에러가 나는지 ㅠㅠ

import java.util.Arrays;

class Solution {
    boolean[] checkNodeVisited;

    public int networkCount(int[][] computer, int linkNodeIndex){
        int count = 0;
        checkNodeVisited[linkNodeIndex] = true;

        for (int i = 0 ; i < computer.length ; i++){
            if(computer[linkNodeIndex][i] == 1 && linkNodeIndex != i){
               computer[linkNodeIndex][i] = computer[i][linkNodeIndex] = 0;
               count += networkCount(computer, i);
            }
        }
        if(linkNodeIndex == 0) return count;
        else return 1;
    }

    public int solution(int n, int[][] computers) {
        checkNodeVisited = new boolean[n];
        Arrays.fill(checkNodeVisited, false);
        int visitedNodeCount = networkCount(computers, 0);
        int notVisitedNodeCount = 0;
        for(int i = 0 ; i < checkNodeVisited.length ; i ++){
            if(!checkNodeVisited[i])notVisitedNodeCount++;
        }

        return notVisitedNodeCount + visitedNodeCount;
    }
}

나는 우선

  1. Link된 node(computer[linkNodeIndex][i] == 1 인 경우) 이고, 자기 자신이 아닌 경우에 DFS 탐색.
    1. computer 배열은 무조건 대칭형 이므로 index가 대칭인 경우도 0으로 초기화 시켜줌. 이미 방문했다는걸 체크하기 위함.
    2. 이렇게 되면 해당 index의 값은 0으로 처리되어 서로 참조해서 무한 루프가 생기는 경우는 없음.
  2. 방문한 Node는 하나의 네트워크로 처리되므로
    1. 방문한 Node는 checkNodeVisited로 체크
    2. 마지막에 방문하지 않은 Node는 독립된 Network이므로 따로 더해줌

이렇게 생각했는데, 너무 꼬아서 생각한 것 같다.

어차피 한번 방문한 Node는 같은 Network이기 때문에 다시 방문할 필요가 없다. 라는 생각을 못해서 더 복잡하게 풀었다.


🥕 다른분 코드

이상하게 구글에 찾아보면 전부 비슷한 코드들이다. 생각하는게 같은건지 같은걸 돌려쓰는건지 모르겠당 ㅋㅋㅋ

class Solution {
    static boolean[][] link;

    public void dfs(int[][] computers, int linkedNodeIdx, int n) {
        for(int i = 0; i < n; i++) {            
            if(computers[linkedNodeIdx][i] == 1 && !link[linkedNodeIdx][i]) {
                link[linkedNodeIdx][i] = link[i][linkedNodeIdx] = true;
                dfs(computers, i, n);
            }
        }
    }

    public int solution(int n, int[][] computers) {
        int answer = 0;
        link = new boolean[n][n];

        for(int i = 0; i < n; i++) {
            if(!link[i][i]) {
                dfs(computers, i, n);
                answer++;
            }
        }
        return answer;
    }
}

문제 설명에서 말한 조건을 그대로 포함하고 있다. 같은 노드를 방문했으면 하나의 네트워크로 치고 다시 방문하지 않는다.