섬 연결하기
문제 설명
n개의 섬 사이에 다리를 건설하는 비용(costs)이 주어질 때, 최소의 비용으로 모든 섬이 서로 통행 가능하도록 만들 때 필요한 최소 비용을 return 하도록 solution을 완성하세요.
다리를 여러 번 건너더라도, 도달할 수만 있으면 통행 가능하다고 봅니다. 예를 들어 A 섬과 B 섬 사이에 다리가 있고, B 섬과 C 섬 사이에 다리가 있으면 A 섬과 C 섬은 서로 통행 가능합니다.
제한사항
섬의 개수 n은 1 이상 100 이하입니다.
costs의 길이는 ((n-1) * n) / 2이하입니다.
임의의 i에 대해, costs[i][0] 와 costs[i] [1]에는 다리가 연결되는 두 섬의 번호가 들어있고, costs[i] [2]에는 이 두 섬을 연결하는 다리를 건설할 때 드는 비용입니다.
같은 연결은 두 번 주어지지 않습니다. 또한 순서가 바뀌더라도 같은 연결로 봅니다. 즉 0과 1 사이를 연결하는 비용이 주어졌을 때, 1과 0의 비용이 주어지지 않습니다.
모든 섬 사이의 다리 건설 비용이 주어지지 않습니다. 이 경우, 두 섬 사이의 건설이 불가능한 것으로 봅니다.
연결할 수 없는 섬은 주어지지 않습니다.
입출력 예
n costs return
4 [[0,1,1],[0,2,2],[1,2,5],[1,3,1],[2,3,8]] 4풀이
섬을 최소 비용으로 모두 연결하는 문제는 최소 비용 신장 트리를 구하는 크루스칼 알고리즘의 전형적인 문제이다.
모든 간선을 거리순으로 정렬하고 작은 수의 간선을 뽑아 사이클을 생성하지 않은 선에서 연결하면 된다.
code
import java.util.*;
class Solution {
public int solution(int n, int[][] costs) {
int answer = 0;
Arrays.sort(costs,(a,b) -> {return a[2] - b[2];});
Set<Integer> set = new HashSet<>();
int[] parent = new int[n];
for(int i = 0; i < n; i++){
parent[i] = i;
}
for(int[] arr : costs){
int pa = findParent(parent,arr[0]);
int pb = findParent(parent,arr[1]);
if(pa != pb){
answer += arr[2];
unionParent(parent,pa, pb);
}
}
return answer;
}
static int findParent(int[] parent, int n){
if(parent[n] != n){
return findParent(parent, parent[n]);
}
return parent[n];
}
static void unionParent(int[] parent, int n, int m){
if(n < m){
parent[m] = n;
}else{
parent[n] = m;
}
}
}회고
처음에는 단수히 가장 작은 간선을 뽑아 양쪽이 둘다 선택된 적이 없으면 추가하는 순으로 해결했었다.
그러나 이렇게 풀면 1-2-3 이 연결되어 있고 3-4가 연결되어 있을 때 문제가 발생했다.
3-4는 연결되지 않았는데도 3과 4가 사용되었기 때문에 문제가 발생한 것이다.
어떻게 풀어야할지 고민하다 알고리즘 책을 확인하였더니 서로소 집합이라는 것이 있었다.
덕분에 가볍게 공부하고 풀어내긴 했지만 아직 익숙하진 않은 것 같다.
서로소 집합에 대해 더 공부하고 익숙해져야겠다.
'알고리즘' 카테고리의 다른 글
| [프로그래머스] 순위 검색 (java) (0) | 2022.03.27 |
|---|---|
| [프로그래머스] 수식 최대화 (0) | 2022.03.27 |
| [프로그래머스] 비밀지도 (0) | 2022.03.27 |
| [프로그래머스] 베스트 앨범 (0) | 2022.03.27 |
| [프로그래머스] 방금 그곡 (0) | 2022.03.27 |