본문 바로가기

Algorithm/level2

[ 프로그래머스 - Java & Kotlin ] 9주차_전력망을 둘로 나누기 ( 자바 & 코틀린 )

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
    }
}

문제 링크

 

코딩테스트 연습 - 9주차_전력망을 둘로 나누기

9 [[1,3],[2,3],[3,4],[4,5],[4,6],[4,7],[7,8],[7,9]] 3 7 [[1,2],[2,7],[3,7],[3,4],[4,5],[6,7]] 1

programmers.co.kr

제가 잘못 알고 있거나 잘못된 부분이 있을 경우 알려주시고 추가로 궁금한 점 있으신 분들도 댓글이나 메일 주시면 성실히 답변해 드리겠습니다.🧑🏻‍💻

감사합니다~😄

728x90