네트워크란 컴퓨터 상호 간에 정보를 교환할 수 있도록 연결된 형태를 의미합니다. 예를 들어, 컴퓨터 A와 컴퓨터 B가 직접적으로 연결되어있고, 컴퓨터 B와 컴퓨터 C가 직접적으로 연결되어 있을 때 컴퓨터 A와 컴퓨터 C도 간접적으로 연결되어 정보를 교환할 수 있습니다. 따라서 컴퓨터 A, B, C는 모두 같은 네트워크 상에 있다고 할 수 있습니다.
컴퓨터의 개수 n, 연결에 대한 정보가 담긴 2차원 배열 computers가 매개변수로 주어질 때, 네트워크의 개수를 return 하도록 solution 함수를 작성하시오.
제한사항
n-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개의 네트워크가 있습니다.
예제 #2
아래와 같이 1개의 네트워크가 있습니다.
크루스칼 알고리즘을 응용해서 풀었다. (내가 정리한 내용은 여기)
컴퓨터를 노드로, 컴퓨터 간의 연결을 간선으로 본다.
노드의 부모를 저장하는 배열을 만들어서, computers
로 노드끼리 어떻게 연결되어 있는지 봐서 부모를 업데이트한다.
부모 배열에 computers
의 연결정보를 모두 반영했다면, 네트워크 당 각기 다른 부모를 가질 것이다.
+ 2번에서 computers
를 순회할 때 모든 값을 확인하지 않아도 된다.
배열의 (i, j)
요소는 연결되어 있다면 1
, 아니라면 0
으로 나타낸다.
이 말은 즉, (i, j)
와 (j, i)
의 값은 항상 같고 (i, i)
는 항상 1
이 된다는 것이다.
예제 1번을 보기쉽게 행렬처럼 표현하면 이렇다.
저 오른쪽 위 부분이나 왼쪽 아래 부분 둘 중 한 곳만 확인하면 된다.
소스코드
function solution(n, computers) {
// 간선의 부모 저장
let parent = [];
for (let i=0; i<n; i++) parent.push(i);
// 연결되어 있다면 부모를 최솟값으로 갱신
// 행렬의 오른쪽 위 방향만 확인하면 됨 (대각선 반대편은 동일하므로 확인 불필요)
for (let i=0; i<n-1; i++) {
for (let j=i+1; j<n; j++) {
if (computers[i][j] === 1) {
let minI = -1, maxI = -1;
if (parent[i] < parent[j]) minI = i, maxI = j;
else minI = j, maxI = i;
let exParent = parent[maxI];
parent[maxI] = parent[minI];
// parent 안에 그 전의 최솟값이 존재한다면 지금의 최솟값으로 갱신
if (parent.includes(exParent)) {
parent = parent.map((x) => {
if (x === exParent) return parent[minI];
else return x;
});
}
}
}
}
// set로 바꿔서 중복 없앤 후, set의 길이를 return
return new Set(parent).size;
}
반복문이 많이 중첩되어서 자료 크기가 크다면 효율적이지 않을 것 같다.