[Programmers 알고리즘][86971] 9주차_전력망을 둘로 나누기
2021. 10. 18. 00:39ㆍAlgorithm
반응형
문제 설명
Programmers Weekly Challenge
9 week
송전탑의 개수 n, 그리고 전선 정보 wires가 매개변수로 주어지며, n개의 송전탑이 하나의 트리 형태로 연결되어 있습니다.
전선들 중 하나를 끊어서 송전탑 개수가 가능한 비슷하도록 두 전력망으로 나누었을 때,
두 전력망이 가지고 있는 송전탑 개수의 차이(절대값)를 return 하도록 solution 함수를 완성해주세요.
제한사항
- n은 2 이상 100 이하인 자연수입니다.
- wires는 길이가 n-1인 정수형 2차원 배열입니다.
- wires의 각 원소는 [v1, v2] 2개의 자연수로 이루어져 있으며, 이는 전력망의 v1번 송전탑과 v2번 송전탑이 전선으로 연결되어 있다는 것을 의미합니다.
- 1 ≤ v1 < v2 ≤ n 입니다.
- 전력망 네트워크가 하나의 트리 형태가 아닌 경우는 입력으로 주어지지 않습니다.
입출력 예
N | wires | result |
9 | [[1,3],[2,3],[3,4],[4,5],[4,6],[4,7],[7,8],[7,9]] | 3 |
4 | [[1,2],[2,3],[3,4]] | 0 |
7 | [[1,2],[2,7],[3,7],[3,4],[4,5],[6,7]] | 1 |
문제 풀이
- wires에 따라, 트리를 완성 (addConnect)
- tree = [], tree[v-1] = [connected list]로 구성됨 (v는 1부터 시작, tree는 0부터 시작)
- wire = [v1, v2] 에 대해 tree에 각각 연결 노드 저장해준다. (v1 -> v2, v2 -> v1)
- 다시 wires를 돌며, 각 전선이 끊어졌을 때의 차이를 구하고 min을 갱신 (updateDiff)
- 한쪽 전력망의 송전탑 개수를 구한다.
- 타겟 노드의 연결된 노드 중 끊어진 노드를 제외한 모든 노드의 개수를 구한다.
- 각 노드가 혼자 남을때 까지 재귀 방문하여 총 개수를 구한다.
- 차이를 구한 후 min을 갱신한다. (차이 = 절대값(C*2 - N))
- 한쪽 전력망의 송전탑 개수를 구한다.
Check Point
- 트리는 N개의 노드와, N-1개의 간선으로 이루어져 있다.
- 하나의 트리 형태이므로, 최대 개수 차이는 N-1이다.
- 한쪽 전력망(트리)의 송전탑(노드) 개수가 C라고 했을 때, 다른쪽의 개수는 N-C이다.
- 즉, 차이는 절대값(C - (N - C))이다. 👉 절대값(C*2 - N)
- 전력탑의 개수를 구할 때 체크하는 노드의 수를 항상 추가한다. (+1)
- v번 노드에 연결된 노드의 총 개수를 count(v)라고 할 때
- 총 개수 = count(v) + 1(자기 자신)
- v번 노드에 연결된 노드의 총 개수를 count(v)라고 할 때
- 인덱스와 문제의 전선 정보(노드 숫자)가 다르지 않은지 잘 체크하자.
- 나의 경우 input 전선 정보(1 ≤ v1 < v2 ≤ n)이지만, Tree 인덱스는 0~n-1로 지정했다.
Code
효율성보다 가독성에 중점을 둔 코드입니다.
function solution(n, wires) {
class Tree {
tree;
min;
constructor(n) {
this.tree = new Array(n);
this.min = n-1;
}
addConnect(v1, v2) {
this.connect(v1, v2);
this.connect(v2, v1);
}
connect(v, target) {
const connected = this.tree[v-1] || [];
connected.push(target);
this.tree[v-1] = connected;
}
size(v) {
return (this.tree[v-1] || []).length;
}
getCount(v, except) {
if(this.size(v) === 1)
return 1;
const connected = this.tree[v-1] || [];
return connected.reduce((pev, cur) => {
if (cur === except) return pev;
return pev + this.getCount(cur, v);
}, 0) + 1;
}
updateDiff(v1, v2) {
const v1Count = this.getCount(v1, v2);
const diff = Math.abs(v1Count * 2 - n);
this.min = Math.min(this.min, diff);
}
}
const tree = new Tree(n);
wires.forEach(([v1, v2]) => tree.addConnect(v1, v2));
wires.forEach(([v1, v2]) => tree.updateDiff(v1, v2));
return tree.min;
}
더 생각해보기
- 다른 풀이들을 보니, DP 문제로 메모이제이션 방식으로 좀 더 시간 복잡도를 줄일 수 있을 것 같다.
반응형