1. 문제
코딩테스트 연습 - 도넛과 막대 그래프 | 프로그래머스 스쿨 (programmers.co.kr)
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
2. 설명
각각의 특성을 파악하는 것이 우선이다.
먼저 그래프의 그림을 보자.
그리고 예제에 해당하는 그래프를 보자.
각각의 특징들을 나열해보자.
- 생성된 노드 : 들어오는 간선은 없고, 나가는 간선이 2개 이상이다.
- 막대 모양 그래프 : 나가는 간선 1개 + (들어오는 간선 1개 & 나가는 간선 1개) * N + 들어오는 간선 1개
- 도넛 모양 그래프 : (들어오는 간선 1개 & 나가는 간선 1개) * N
- 8자 모양 그래프 : 들어오는 간선 1개 & 나가는 간선 2개 + (들어오는 간선 1개 & 나가는 간선 1개) * N
위의 특징들로 답을 도출해보자.
- 먼저 생성된 노드를 찾고 생성된 노드랑 관련된 간선들을 제거한다.
이때 생성된 노드와 연결된 간선의 수는 전체 그래프의 개수와 같으니 따로 저장해 놓는다. - 3개의 그래프 중에 나가는 간선이 없는 노드는 막대 모양 그래프 뿐이다.
나가는 간선이 없는 노드들의 개수를 세어 막대 모양 그래프로 카운팅한다. - 들어오고 나가는 간선의 개수가 2개를 가지는건 8자 모양 그래프 뿐이다.
해당하는 노드들의 개수를 세어 8자 모양 그래프로 카운팅한다. - 전체 그래프의 개수에서 위 두 개 그래프의 개수를 빼면 남은 도넛 모양 그래프의 개수가 된다.
3. 코드
위 설명 대로 진행해도 문제가 해결되지만, 성능 이슈가 발생한다.
첫 코드를 저 특징대로 짰었는데, 반복문이 두 개가 넘을 시 몇몇 예제들에서 런타임 에러가 발생하였다.
이에 성능을 좀 더 높이기 위해 조금 변형을 했다.
[속도 이슈 해결 방법]
- outcomming, incomming의 길이를 edges의 길이로 설정했었는데, 이것을 문제의 최대 길이인 1000000으로 고정시켜줬다.
생각보다 length를 구하는 함수가 비효율적인가보다.
문제에서 최대 길이가 설정되어 있다면, 그 수를 사용하는게 좋을것 같다. - 여러 반복문이 가장 큰 이슈였는데, 반복문을 하나로 줄여 해결하였다.
들어오는 간선이 2개 이상일때 들어오는 간선이 없으면 생성된 노드일테고, 이외에는 8자 모양 그래프일 수 밖에 없다. 들어오는 간선이 2개 이상인 그래프는 8자 모양 그래프 하나이기 때문이다.
그리고 간선이 2개 이상이 아닐때 나가는 간선이 없으면 막대모양 그래프일 수 밖에 없다.
이렇게되어 생성된 노드를 찾는 반복문과 생성된 노드와 연결된 간선들을 제거하는 반복문이 줄어들게 되어 성능 향상을 바랄 수 있었다. - 추가로 find 노드에서 MaxLength로 코드 실행시 1번 예제가 11초로 해결 됐었는데, 이 또한 비효율적이라 생각하여 nodeSize를 구해서 길이를 제한하여 4초대로 줄였다.
public class Donut {
static int MaxLength = 1000000;
public static void main(String[] args){
//int[][] edges = {{2, 3}, {4, 3}, {1, 1}, {2, 1}};
int[][] edges = {{4, 11}, {1, 12}, {8, 3}, {12, 7}, {4, 2}, {7, 11}, {4, 8}, {9, 6}, {10, 11}, {6, 10}, {3, 5}, {11, 1}, {5, 3}, {11, 9}, {3, 8}};
int[] result = solution(edges);
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
public static int[] solution(int[][] edges) {
// answer = 생성한 점점의 번호, 정점을 생성하기전 도넛 모양 그래프의 수, 막대 모양 그래프의 수, 8자 모양 그래프의 수
int[] answer = new int[4];
int[] outcomming = new int[MaxLength];
int[] incomming = new int[MaxLength];
int nodeSize = 0;
for (int i = 0; i < edges.length; i++){
outcomming[edges[i][0]]++;
incomming[edges[i][1]]++;
if(edges[i][0] > nodeSize) nodeSize = edges[i][0];
if(edges[i][1] > nodeSize) nodeSize = edges[i][1];
}
findNode(nodeSize, outcomming, incomming, answer);
return answer;
}
static void findNode(int nodeSize, int[] outcomming, int[] incomming , int[] answer){
int totalGraph = 0;
for (int i = 1; i <= nodeSize; i++){
if(outcomming[i] >= 2){
if(incomming[i] == 0){
answer[0] = i;
totalGraph = outcomming[i];
}else answer[3]++;
}else if(outcomming[i] == 0) answer[2]++;
}
answer[1] = totalGraph - answer[2] - answer[3];
}
}
반응형
'Algorithm > - Coding Test' 카테고리의 다른 글
요격 시스템 (0) | 2024.07.19 |
---|---|
괄호 짝 맞추기 (0) | 2024.05.08 |
석유 시추 (0) | 2024.04.24 |