Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 프로그래머스
- 괄호 회전하기
- java
- 데이터
- 자바
- swea
- 부동소수점
- 컴퓨터구조
- 베스트 앨범
- 티스토리챌린지
- sw expert academy
- 조합
- Comparable
- 오블완
- 고정소수점
- 컴퓨터 구조
- 요세푸스
- 다단계 칫솔 판매
- 운영 체제
- 구현
- 백준
- 기능 개발
- 코테
- 도둑질
- 표 편집
- 메뉴 리뉴얼
- Call-by-Value
- 순열
- Comparator
- 토마토
Archives
- Today
- Total
감자는 아직 꿈을 꾼다.
[프로그래머스-java] Lv.2 전력망을 둘로 나누기 본문
알고리즘 : DFS
문제 설명
https://school.programmers.co.kr/learn/courses/30/lessons/86971
내 풀이
-> 가장 직관적인 풀이 + 효율성은 떨어짐
전력망을 둘로 나눈다는 개념에서 보면 결국 2개의 서브트리의 노드의 갯수 차이를 최소화하는 목표의 문제다.
처음에는 DFS만으로 서브트리를 나눠가면서 백트래킹으로 풀려고 했으나 실패했고(이게 더 좋은 풀이)
결국 가장 간단하게 생각 할 수있는 간선을 끊어버리고 DFS를 진행하는 방식을 택했다.
간선을 끊어 낸 다음에 DFS를 진행하면 결국 서브트리의 노드수가 count되고,
전체 n에서 count를 빼면 그게 또 다른 서브트리의 노드수가 되므로,
두개의 서브트리의 뺄셈을 할 경우 그게 차이값이 된다.
이 차이값의 MIN을 찾아가는 과정
시간 복잡도
내 풀이에서는 시간복잡도가 좋지는 않다.
(wire의 갯수 * 노드의 수) 이므로 최악의 경우 V^2이 되어버린다.
이것보다 더 좋게 DFS한번으로 끝내는 풀이도 있다.
import java.util.*;
class Solution {
private static int N;
private static int count;
private static boolean[] visited;
private static ArrayList<Integer>[] adj;
private static void dfs(int now){
if (!visited[now]) visited[now] = true;
count++;
for (int next : adj[now]){
if (!visited[next]){
dfs(next);
}
}
}
private static void init(){
count = 0;
visited = new boolean[N+1];
}
public int solution(int n, int[][] wires) {
N = n;
adj = new ArrayList[N+1];
int answer = Integer.MAX_VALUE;
for (int i = 0 ; i<= n ; i++){
adj[i] = new ArrayList<>();
}
for (int[] edge : wires){
adj[edge[0]].add(edge[1]);
adj[edge[1]].add(edge[0]);
}
for (int[] edge : wires) {
// 간선 제거
adj[edge[0]].remove(Integer.valueOf(edge[1]));
adj[edge[1]].remove(Integer.valueOf(edge[0]));
// dfs 진행
init();
dfs(edge[0]);
int subTree = count;
int remainTree = n - subTree;
answer = Math.min(answer,Math.abs(remainTree - subTree));
// 간선 복구
adj[edge[0]].add(edge[1]);
adj[edge[1]].add(edge[0]);
}
return answer;
}
}
더 좋은 풀이
한번의 DFS 즉 시간복잡도 N으로 끝내는 풀이가 있다.
결국 전력망의 구조는 무조건 하나의 트리이고, 두개의 서브트리의 차는 사실 한개의 전력망을 구한다음 전체에서 2번빼면된다.
그러므로 DFS로 자식의 갯수를 전부 탐색하면서 최솟값을 갱신하는 것
전체노드 - 자식트리의 노드수 * 2 이 식의 절대값이 가장 작은 것을 찾으면 된다.
import java.util.*;
class Solution {
public static int N;
public static boolean[] visited;
public static int answer;
public static ArrayList<Integer>[] adj;
public int solution(int n, int[][] wires) {
answer = Integer.MAX_VALUE;
N = n;
visited = new boolean[N+1];
adj = new ArrayList[N+1];
for(int i = 0; i<=N;i++){
adj[i] = new ArrayList<>();
}
for (int [] edge : wires){
adj[edge[0]].add(edge[1]);
adj[edge[1]].add(edge[0]);
}
dfs(1);
return answer;
}
private static int dfs(int now){
if (!visited[now]) visited[now] = true;
int sum = 0;
for (int next : adj[now]){
if (!visited[next]){
// 자식 노드의 수
int cnt = dfs(next);
answer = Math.min(answer,Math.abs(N - cnt*2));
sum+=cnt;
}
}
return sum+1;
}
}
'코테적 감자 > 프로그래머스' 카테고리의 다른 글
[프로그래머스-java] Lv.4 도둑질 (0) | 2024.11.19 |
---|---|
[프로그래머스-java] Lv.3 경주로 건설 (2) | 2024.11.13 |
[프로그래머스] Lv.3 다단계 칫솔 판매 (0) | 2024.11.05 |
[프로그래머스] Lv.2 메뉴 리뉴얼 (1) | 2024.11.05 |
[프로그래머스] Lv.3 베스트 앨범 (0) | 2024.11.04 |