728x90
( 위클리 챌린지 / 9주차_전력방을 둘로 나누기 )
[문제]
문제 설명
n개의 송전탑이 전선을 통해 하나의 트리 형태로 연결되어 있습니다. 당신은 이 전선들 중 하나를 끊어서 현재의 전력망 네트워크를 2개로 분할하려고 합니다. 이때, 두 전력망이 갖게 되는 송전탑의 개수를 최대한 비슷하게 맞추고자 합니다.
송전탑의 개수 n, 그리고 전선 정보 wires가 매개변수로 주어집니다. 전선들 중 하나를 끊어서 송전탑 개수가 가능한 비슷하도록 두 전력망으로 나누었을 때, 두 전력망이 가지고 있는 송전탑 개수의 차이(절대값)를 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 |
입출력 예 #1
- 다음 그림은 주어진 입력을 해결하는 방법 중 하나를 나타낸 것입니다.
- 4번과 7번을 연결하는 전선을 끊으면 두 전력망은 각 6개와 3개의 송전탑을 가지며, 이보다 더 비슷한 개수로 전력망을 나눌 수 없습니다.
- 또 다른 방법으로는 3번과 4번을 연결하는 전선을 끊어도 최선의 정답을 도출할 수 있습니다.
입출력 예 #2
- 다음 그림은 주어진 입력을 해결하는 방법을 나타낸 것입니다.
- 2번과 3번을 연결하는 전선을 끊으면 두 전력망이 모두 2개의 송전탑을 가지게 되며, 이 방법이 최선입니다.
입출력 예 #3
- 다음 그림은 주어진 입력을 해결하는 방법을 나타낸 것입니다.
- 3번과 7번을 연결하는 전선을 끊으면 두 전력망이 각각 4개와 3개의 송전탑을 가지게 되며, 이 방법이 최선입니다.
[코드]
자바
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
import java.util.HashSet;
class Solution {
public int solution(int n, int[][] wires) {
int answer = n;
ArrayList<ArrayList<Integer>> arr = new ArrayList<>(); // 모든 wires정보
for (int i = 0; i < n; i++) arr.add(new ArrayList<>());
// 양방향을 체크해 주기 위함
for (int i = 0; i < wires.length; i++) {
arr.get(wires[i][0] - 1).add(wires[i][1] - 1);
arr.get(wires[i][1] - 1).add(wires[i][0] - 1);
}
// 두개의 트리 카운트
for (int[] w : wires) {
// 각 트리의 노드 개수를 계산
int tree1 = countNode(arr, arr.get(w[0] - 1), w[0] - 1, w[1] - 1);
int tree2 = countNode(arr, arr.get(w[1] - 1), w[1] - 1, w[0] - 1);
answer = Math.min(answer, Math.abs(tree1 - tree2));
}
return answer;
}
public int countNode(ArrayList<ArrayList<Integer>> arr, ArrayList<Integer> startNode, int s, int e) {
HashSet<Integer> visit = new HashSet<>();
Queue<Integer> q = new LinkedList<>();
visit.add(s);
// 현재 노드에 대한 처리
for (int i = 0; i < startNode.size(); i++) {
// e랑 연결된 노드를 끊어주기 위함
if (startNode.get(i) == e) continue;
q.offer(startNode.get(i));
visit.add(startNode.get(i));
}
// 전체 연결을 확인
while (!q.isEmpty()) {
int node = q.poll();
for (int i = 0; i < arr.get(node).size(); i++) {
// 만일 이미 방문했던 노드면 continue
if (visit.contains(arr.get(node).get(i))) continue;
// 방문하지 않은 노드 큐에 추가 후 현재 노드 방문처리
q.offer(arr.get(node).get(i));
visit.add(arr.get(node).get(i));
}
}
return visit.size();
}
}
코틀린
import java.util.Queue
import java.util.LinkedList
class Solution {
fun solution(n: Int, wires: Array<IntArray>): Int {
var answer = n
val arr = Array<MutableList<Int>>(n){mutableListOf()} // 모든 wires정보
// 양방향을 체크해 주기 위함
wires.forEach{
arr[it[0] - 1].add(it[1] - 1)
arr[it[1] - 1].add(it[0] - 1)
}
// 각 트리를 카운트 후 차이가 가장 적은 값을 answer에 저장
wires.forEach{
answer = Math.min(answer, Math.abs(countNode(arr, arr[it[0]-1], it[0]-1, it[1]-1) - countNode(arr, arr[it[1]-1], it[1]-1, it[0]-1)))
}
return answer
}
fun countNode(arr:Array<MutableList<Int>>, startNode:MutableList<Int>, s:Int, e:Int):Int{
val hs = HashSet<Int>()
val q:Queue<Int> = LinkedList<Int>()
// 현재 노드에 대한 처리
hs.add(s)
for(n in startNode){
// e랑 연결된 노드를 끊어주기 위함
if(n == e) continue
hs.add(n)
q.offer(n)
}
// 전체 연결을 확인
while(q.isNotEmpty()){
val now = q.poll()
for(i in arr[now].indices){
// 이미 방문했던 노드면 continue
if(hs.contains(arr[now][i])) continue
hs.add(arr[now][i])
q.offer(arr[now][i])
}
}
return hs.size
}
}
제가 잘못 알고 있거나 잘못된 부분이 있을 경우 알려주시고 추가로 궁금한 점 있으신 분들도 댓글이나 메일 주시면 성실히 답변해 드리겠습니다.🧑🏻💻
감사합니다~😄
728x90
'Algorithm > level2' 카테고리의 다른 글
[ 프로그래머스 - Java & Kotlin ] n^2 배열 자르기 ( 자바 & 코틀린 ) (0) | 2021.10.17 |
---|---|
[ 프로그래머스 - Java & Kotlin ] 튜플( 자바 & 코틀린 ) (0) | 2021.10.14 |
[ 프로그래머스 - Java & Kotlin ] 5주차_모음사전 ( 자바 & 코틀린 ) (0) | 2021.10.13 |
[ 프로그래머스 - MySQL ] 고양이와 개는 몇 마리 있을까 ( MySQL ) (0) | 2021.10.12 |
[ 프로그래머스 - MySQL ] 루시와 엘라 찾기 ( MySQL ) (0) | 2021.10.12 |