| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- flutter getx
- 티스토리챌린지
- 알고리즘
- 코테
- DP
- 코딩테스트준비
- 99클럽
- 개발자취업
- Laravel
- C++
- 코딩테스트
- 코딩테스트 준비
- 라라벨
- c++ 코테
- 뷰
- vue
- 코테 파이썬
- 파이썬
- Flutter
- 항해99
- Python
- 플러터
- 백준
- til
- 파이썬 코테
- 오블완
- 안드로이드
- ML
- react
- 개발자 취업
- Today
- Total
잡다로그
[JS/코테] 백준 1260 DFS와 BFS 본문
DFS와 BFS
문제 및 조건 설명: https://www.acmicpc.net/problem/1260

알고리즘 설계
💡idea.
- 상세 구현 방법은 다 다르지만, BFS, DFS 구현의 스타트는 각각 Stack, Queue를 기준으로 반복한다는 것이다.
방문할 것들이 저장되고, 꺼내서 검사한다. - stack을 사용하는 DFS 구현을 Iterative DFS 라고 한다.
- 입력값은 인접리스트로 받는다. 이 때, 번호가 작은 정점을 우선으로 하기 위해 오름차순으로 정렬한다.
🎲step.
입력값은 인접리스트로 받고, 오름차순 정렬한다. 양방향 그래프이므로 두 번 push 해준다.
출력값은 배열을 문자열로 바꾸어서 숫자만 출력한다.
let input = []; // 전체 입력값을 넣어줄 리스트 생성
let g = [];
rl.on("line", (line) => {
input.push(line);
}).on("close", () => {
const [n, m, v] = input[0].split(" ").map(Number);
g = Array.from({ length: n + 1 }, () => []);
for (let i = 1; i <= m; i++) {
const [a, b] = input[i].split(" ").map(Number);
g[a].push(b);
g[b].push(a);
}
// 오름차순 정렬
g.forEach((adjList) => adjList.sort((a, b) => a - b));
console.log(dfs(n, g, v).join(" "));
console.log(bfs(n, g, v).join(" "));
});
기본 Iterative DFS는 이 포스팅을 참고했다.
* 부모 노드는 추가할 필요없지만, 다른 응용 문제를 위해 연습 구현했다.
변형한 부분은, 번호가 작은 정점을 우선 방문하기 위해 역순으로 stack에 추가해준 부분이다.
const dfs = (n, g, start) => {
let result = [];
let visited = Array(n + 1).fill(false);
const stack = [start];
while (stack.length) {
const cur = stack.pop();
if (!visited[cur]) {
visited[cur] = true;
result.push(cur);
// 큰 숫자부터 스택에 넣어야 pop할 때 작은 숫자부터 나오도록 역순 정렬
for (let i = g[cur].length - 1; i >= 0; i--) {
const node = g[cur][i];
if (!visited[node]) stack.push(node);
}
}
}
return result;
};
BFS도 반복문과 queue를 사용해서 구현한다.
queue에 추가(push)할 때는 이미 오름차순 정렬되어 있으므로 순차 반복해준다. queue 이므로 pop대신 shift 메서드를 사용한다.
const bfs = (n, g, start) => {
let result = [];
let visited = Array(n + 1).fill(false);
const queue = [start];
visited[start] = true;
while (queue.length) {
const cur = queue.shift();
result.push(cur);
// 작은 숫자부터 큐에 넣기 위해 오름차순 정렬
for (const node of g[cur]) {
if (!visited[node]) {
visited[node] = true;
queue.push(node);
}
}
}
return result;
};
알고리즘 구현
위의 모든 구현을 합친 정답 코드는 아래와 같다.
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const dfs = (n, g, start) => {
let result = [];
let visited = Array(n + 1).fill(false);
const stack = [start];
while (stack.length) {
const cur = stack.pop();
if (!visited[cur]) {
visited[cur] = true;
result.push(cur);
for (let i = g[cur].length - 1; i >= 0; i--) {
const node = g[cur][i];
if (!visited[node]) stack.push(node);
}
}
}
return result;
};
const bfs = (n, g, start) => {
let result = [];
let visited = Array(n + 1).fill(false);
const queue = [start];
visited[start] = true;
while (queue.length) {
const cur = queue.shift();
result.push(cur);
for (const node of g[cur]) {
if (!visited[node]) {
visited[node] = true;
queue.push(node);
}
}
}
return result;
};
let input = [];
let g = [];
rl.on("line", (line) => {
input.push(line);
}).on("close", () => {
const [n, m, v] = input[0].split(" ").map(Number);
g = Array.from({ length: n + 1 }, () => []);
for (let i = 1; i <= m; i++) {
const [a, b] = input[i].split(" ").map(Number);
g[a].push(b);
g[b].push(a);
}
g.forEach((adjList) => adjList.sort((a, b) => a - b));
console.log(dfs(n, g, v).join(" "));
console.log(bfs(n, g, v).join(" "));
});
나다어
- 정리하자면, 구현을 위해서는 ①원본 그래프(input값) ②Stack/Queue ③방문확인배열 이 필요하다.
- 입력값을 정리하는 것 또한 중요하다. 오늘 문제에서는 인접 리스트로, 오름차순 정렬로 그래프를 정리했다.
- 구조 분해 할당은 배열을 펼치고 반복할 필요 없이 유용하게 쓰인다.
✔️이차원 배열 선언
let numArr = new Array(n + 1).fill([]);
let numArr = new Array(n + 1).fill().map(() => []);
첫 번째와 같이 선언하면, 이차원 배열 내부 원소는 모두 같은 참조를 가지게 되어 특정 인덱스에 값을 추가하는 것이 불가능하고 모든 인덱스에 값이 추가된다. 각 인덱스에 서로 다른 배열을 넣어주기 위해서는 반복문을 이용해야 한다.
let numArr = Array.from({ length: n + 1 }, () => []);
fill 메서드는 배열을 undefined로 채운 후, map을 통해 요소를 추가하도록 동작한다. 그러나 Array.from 메서드를 사용하면 배열을 생성하면서 각 요소에 콜백 함수가 바로 실행되기 때문에 조-금 더 효율적이라고 볼 수 있다.
참고:
https://chamdom.blog/dfs-using-js/
[알고리즘] JavaScript로 구현하는 DFS
dfs에 대해 알아보기 전에 우선 그래프에 대한 이해가 필요하다. 그래프에 대한 설명은 여기 에 자세히 정리해두었다. DFS란? DFS(Depth-First-Search) 는 …
chamdom.blog
'Algorithm' 카테고리의 다른 글
| [99클럽 코테 스터디] 26일차 TIL - 스택/큐, Baseball Game (0) | 2024.06.25 |
|---|---|
| [99클럽 코테 스터디] 25일차 TIL - 스택/큐, Removing Stars From a String (0) | 2024.06.24 |
| [99클럽 코테 스터디] 24일차 TIL - 스택/큐, Number of Recent Calls (0) | 2024.06.24 |
| [99클럽 코테 스터디] 23일차 TIL - 스택/큐, Number of Students Unable to Eat Lunch (0) | 2024.06.23 |
| [99클럽 코테 스터디] 22일차 TIL - 정렬, Find Target Indices After Sorting Array (0) | 2024.06.22 |