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
- group by
- 동적계획법
- DP
- dfs
- LEVEL 2
- javascript
- programmers
- select
- 파이썬
- Lv. 0
- softeer
- 프로그래머스
- level 3
- 소프티어
- 자바스크립트
- Lv. 2
- bfs
- 오블완
- join
- Lv. 3
- Lv. 1
- 깊이 우선 탐색
- 너비 우선 탐색
- C언어
- 티스토리챌린지
- Java
- SQL
- Dynamic Programming
- Python
- SQL 고득점 KIT
Archives
- Today
- Total
몸과 마음이 건전한 SW 개발자
프로그래머스 [Lv. 2] 도넛과 막대 그래프 {언어 : JavaScript} [반례 포함] 본문
문제 링크
https://school.programmers.co.kr/learn/courses/30/lessons/258711?language=javascript
정답 코드
function solution(edges) {
const n = 1000001;
const answer = [0, 0, 0, 0]; // 정점, 도넛, 막대, 8자
const adjL = Array.from({length: n+1}, () => []);
const visited = Array.from({length: n+1}, () => false);
const inAndOut = Array.from({length: n+1}, () => [0, 0]); // [나감, 들어옴]
edges.forEach(([start, to]) => {
adjL[start].push(to);
inAndOut[start][0] += 1;
inAndOut[to][1] += 1;
});
// 나간게 가장 많고 들어온 것은 없는 정점이 생성한 정점
let [createdNode, nodeCnt] = [0, 0];
inAndOut.forEach(([cntOut, cntIn], idx) => {
if (nodeCnt < cntOut && cntIn === 0) {
createdNode = idx;
nodeCnt = cntOut;
}
})
// 정점 저장
answer[0] = createdNode;
// 탐색
adjL[createdNode].forEach((outNode) => {
// 현재의 돈넛 모양은 무엇인가
let shape = 0;
// 현재 지점이 두 갈래 길로 되어있다면 볼것도 없이 8자 모양
if (adjL[outNode].length === 2) {
shape = 3;
} else {
const stack = [outNode];
visited[outNode] = true;
// 출발 지점으로 돌아왔는가?
let canReturn = false;
// 두 갈래 길로 되어있는가?
let hasTwoWays = false;
while (stack.length) {
const currentNode = stack.pop();
for (const nextNode of adjL[currentNode]) {
if (visited[nextNode]) {
// 일단 막대는 아님
canReturn = true;
continue;
}
// 가는 길이 2개 인가
if (adjL[nextNode].length === 2) {
hasTwoWays = true;
}
visited[nextNode] = true;
stack.push(nextNode);
}
}
if (canReturn) {
if (hasTwoWays) {
// 8자 모양
shape = 3;
} else {
// 도넛 모양
shape = 1;
}
} else {
shape = 2;
}
}
answer[shape] += 1;
})
return answer;
}
풀이 방법
- 반복을 통해서 생성한 정점을 찾는다.
- 정점은 In은 없고 Out만 있으며 최소 2개 이상이기 때문에 Out이 없는 In이 가장 많은 것이 생성한 정점이 된다.
- 생성한 정점과 연결된 정점에서 그래프의 모양을 조사한다.
- 현재의 위치에서 이미 두 갈래 길로 나눠진다면 8자 모양밖에 없다.
- 그래프를 탐색하는데 이미 방문한 곳을 다시 방문한다면 8자 모양과 도넛 모양 중에서 고를 수 있게 canReturn을 true로 바꾼다.
- 탐색 중에 또 두 갈래 길이 생기면 탐색을 종료하고 hasTwoWays를 true로 바꾼다.
- 조사가 끝나면
- canReturn이 false이면 되돌아 오지 않는 그래프 = 막대
- canReturn이 true이면 8자 모양 또는 도넛
- hasTwoWays가 true면 두 갈래 길이 있다 = 8자
- 아니면 = 도넛
- shape에 따라서 개수를 더해주면 끝!
느낀점
- 전에 풀었을 때는 감도 안잡혔는데 이제는 쉽게 느껴진다.
- 다시 풀어보면 좋겠다고 생각한 이유는 리팩토링이 필요해서이다.
- 8자 모양인 것을 알면 굳이 탐색을 이어갈 필요가 없다. => 중간에서 멈추게 하면 좋을듯
- 중간에 n을 edges.length로 했는데 정점은 1부터 100만 까지이며 n이 4라고 해도 정점이 10만, 99만 이렇게 나올 수 있다.
- 만약 런타임 에러가 나온다면 대부분 인덱스 에러이며 다음과 같은 반례를 유추할 수 있다.
- edges = [[1000, 20], [5555, 20], [9876, 9876], [1000, 9876]]
- result = [1000, 1, 1, 0]
'알고리즘 > 풀었지만 다시 보기' 카테고리의 다른 글
Softeer [Level 3] [한양대 HCPC 2023] Hanyang Popularity Exceeding Competition {언어 : JavaScript} (1) | 2024.10.21 |
---|---|
Softeer [Level 3] [한양대 HCPC 2023] Phi Squared {언어 : JavaScript} (2) | 2024.10.21 |
백준 SILVER 1 [11052번] 카드 구매하기 {언어 : Python} (0) | 2024.10.10 |
프로그래머스 [Lv. 3] [PCCP 기출문제] 4번 / 수레 움직이기 {언어 : Python} (1) | 2024.10.09 |
프로그래머스 [Lv. 3] 퍼즐 조각 채우기 {언어 : JavaScript} (5) | 2024.10.08 |