├── CHAPTER_03_그리디
├── 1이될때까지.js
├── 숫자카드게임.js
├── 예제_3-1_거스름돈.js
├── 큰수의법칙_1.js
├── 큰수의법칙_2.js
└── 큰수의법칙_3.js
├── CHAPTER_04_구현
├── 게임개발.js
├── 예제_4-1_상하좌우.js
├── 예제_4-2_시각.js
└── 왕실의나이트.js
├── CHAPTER_05_DFSBFS
├── 미로탈출.js
├── 미로탈출_NO방문처리.js
├── 예제_5-1_스택.js
├── 예제_5-2_큐.js
├── 예제_5-3_재귀 함수.js
├── 예제_5-4_재귀 함수 종료.js
├── 예제_5-5_2가지 방식으로 구현한 팩토리얼.js
├── 예제_5-6_인접 행렬 방식.js
├── 예제_5-7_인접 리스트 방식.js
├── 예제_5-8_DFS.js
├── 예제_5-9_BFS.js
├── 음료수얼려먹기_BFS.js
├── 음료수얼려먹기_DFS.js
└── 추가_연결 리스트 큐.js
├── CHAPTER_06_정렬
├── 두 배열의 원소 교체.js
├── 성적이 낮은 순서로 학생 출력하기.js
├── 예제_6-1_선택 정렬.js
├── 예제_6-2_삽입 정렬.js
├── 예제_6-3_퀵 정렬.js
├── 예제_6-4.자바스크립트의 장점을 살린 퀵 정렬.js
├── 예제_6-5.계수 정렬.js
└── 위에서 아래로.js
├── CHAPTER_07_이진탐색
├── 떡볶이 떡 만들기.js
├── 부품 찾기_계수 정렬.js
├── 부품 찾기_이진 탐색.js
├── 부품 찾기_집합.js
├── 예제_7-1_순차 탐색.js
├── 예제_7-2_재귀 함수로 구현한 이진 탐색.js
└── 예제_7-3_반복문으로 구현한 이진 탐색.js
├── CHAPTER_08_다이나믹 프로그래밍
├── 1로 만들기.js
├── 개미 전사.js
├── 바닥 공사.js
├── 예제_8-1_피보나치 함수.js
├── 예제_8-2_피보나치 수열 (재귀적).js
├── 예제_8-3_호출되는 함수 확인.js
├── 예제_8-4_피보나치 수열 (반복적).js
└── 효율적인 화폐 구성.js
├── CHAPTER_09_최단경로
├── PriorityQueue.js
├── 미래 도시.js
├── 예제_9-1_간단한 다익스트라.js
├── 예제_9-2_개선된 다익스트라.js
├── 예제_9-3_플로이드 워셜.js
└── 전보.js
├── CHAPTER_10_그래프이론
├── 도시 분할 계획.js
├── 예제_10-1_기본적인 서로소 집합.js
├── 예제_10-2_경로 압축 기법.js
├── 예제_10-3_개선된 서로소 집합.js
├── 예제_10-4_사이클 판별js
├── 예제_10-5_크루스칼.js
├── 예제_10-6_위상 정렬.js
├── 커리큘럼.js
└── 팀 결성.js
├── CHAPTER_11_그리디 문제
├── Q1_모험가 길드.js
├── Q2_곱하기 혹은 더하기.js
├── Q3_문자열 뒤집기.js
├── Q4_만들 수 없는 금액.js
└── Q5_볼링공 고르기.js
├── CHAPTER_12_구현 문제
├── Q10_자물쇠와 열쇠.js
├── Q11_뱀.js
├── Q13_치킨 배달.js
├── Q7_럭키 스트레이트.js
├── Q8_문자열 재정렬.js
└── Q9_문자열 압축.js
├── CHAPTER_13_DFSBFS 문제
├── Q15_특정 거리의 도시 찾기.js
├── Q16_연구소.js
├── Q17_경쟁적 전염.js
├── Q18_괄호 변환.js
├── Q19_연산자 끼워 넣기.js
└── Q20_감시 피하기.js
├── CHAPTER_14_정렬 문제
├── Q23_국영수.js
├── Q24_안테나.js
├── Q25_실패율.js
└── Q26_카드 정렬하기.js
├── CHAPTER_15_이진탐색 문제
├── Q27_정렬된 배열에서 특정 수의 개수 구하기.js
├── Q28_고정점 찾기.js
└── Q29_공유기 설치.js
├── CHAPTER_16_다이나믹 프로그래밍 문제
├── Q31_금광.js
├── Q32_정수 삼각형.js
├── Q34_병사 배치하기.js
└── Q35_못생긴 수.js
├── CHAPTER_17_최단경로 문제
├── Q37_플로이드.js
├── Q38_정확한 순위.js
├── Q39_화성 탐사.js
└── Q40_숨바꼭질.js
├── CHAPTER_18_그래프 이론 문제
├── Q41_여행 계획.js
└── Q43_어두운 길.js
├── README.md
├── solution.js
└── tc.txt
/CHAPTER_03_그리디/1이될때까지.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim();
3 |
4 | let [n, k] = input.split(' ').map((v) => +v);
5 |
6 | function solution(n, k) {
7 | let result = 0;
8 |
9 | while (n > 1) {
10 | if (n % k === 0) {
11 | n /= k;
12 | } else {
13 | n--;
14 | }
15 | result++;
16 | }
17 |
18 | return result;
19 | }
20 |
21 | console.log(solution(n, k));
22 |
--------------------------------------------------------------------------------
/CHAPTER_03_그리디/숫자카드게임.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | let [n, m] = nm.split(' ').map((v) => +v);
6 | arr = arr.map((v) => v.split(' ').map((v) => +v));
7 |
8 | function solution(n, m, arr) {
9 | let result = 0;
10 | for (const cur of arr) {
11 | result = Math.max(result, Math.min(...cur));
12 | }
13 | return result;
14 | }
15 |
16 | console.log(solution(n, m, arr));
17 |
--------------------------------------------------------------------------------
/CHAPTER_03_그리디/예제_3-1_거스름돈.js:
--------------------------------------------------------------------------------
1 | const COIN_TYPES = [500, 100, 50, 10];
2 |
3 | let n = 1260
4 | let count = 0;
5 |
6 | for(const coin of COIN_TYPES){
7 | count += ~~(n / coin);
8 | n %= coin
9 | }
10 |
11 | console.log(count)
--------------------------------------------------------------------------------
/CHAPTER_03_그리디/큰수의법칙_1.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | let [nums, arr] = input;
5 | let [n, m, k] = nums.split(' ').map((value) => +value);
6 | arr = arr.split(' ').map((value) => +value);
7 |
8 | function solution(n, m, k, arr) {
9 | arr.sort((a, b) => b - a);
10 | const first = arr[0];
11 | const second = arr[1];
12 |
13 | let result = 0;
14 | while (1) {
15 | if (m === 0) break;
16 |
17 | result += first * k;
18 | m -= k;
19 |
20 | result += second;
21 | m--;
22 | }
23 |
24 | return result;
25 | }
26 |
27 | console.log(solution(n, m, k, arr));
28 |
--------------------------------------------------------------------------------
/CHAPTER_03_그리디/큰수의법칙_2.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | let [nums, arr] = input;
5 | let [n, m, k] = nums.split(' ').map((value) => +value);
6 | arr = arr.split(' ').map((value) => +value);
7 |
8 | function solution(n, m, k, arr) {
9 | arr.sort((a, b) => b - a);
10 | const first = arr[0];
11 | const second = arr[1];
12 |
13 | let result = 0;
14 | for (let i = 0, tmp = 0; i < m; i++) {
15 | if (tmp === k) {
16 | result += second;
17 | tmp = 0;
18 | } else {
19 | result += first;
20 | tmp++;
21 | }
22 | }
23 | return result;
24 | }
25 |
26 | console.log(solution(n, m, k, arr));
27 |
--------------------------------------------------------------------------------
/CHAPTER_03_그리디/큰수의법칙_3.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | let [nums, arr] = input;
5 | let [n, m, k] = nums.split(' ').map((value) => +value);
6 | arr = arr.split(' ').map((value) => +value);
7 |
8 | function solution(n, m, k, arr) {
9 | arr.sort((a, b) => b - a);
10 | const first = arr[0];
11 | const second = arr[1];
12 |
13 | //가장 큰 수가 더해지는 횟수
14 | let count = ~~(m / (k + 1)) * k;
15 | count += m % (k + 1);
16 |
17 | let result = 0;
18 | result += count * first;
19 | result += (m - count) * second;
20 |
21 | return result;
22 | }
23 |
24 | console.log(solution(n, m, k, arr));
25 |
--------------------------------------------------------------------------------
/CHAPTER_04_구현/게임개발.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | const [nm, abd, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | let [x, y, d] = abd.split(' ').map((v) => +v);
7 | const map = arr.map((v) => v.split(' ').map((v) => +v));
8 |
9 | function solution(n, m, x, y, d, map) {
10 | //북동남서 방향
11 | const DIR = [
12 | [0, -1],
13 | [1, 0],
14 | [0, 1],
15 | [-1, 0],
16 | ];
17 |
18 | //방문 정보
19 | let visited = Array.from(Array(n), () => Array(m).fill(false));
20 | visited[x][y] = true;
21 |
22 | let count = 1; //방문한 칸의 수
23 | let turnTime = 0; //현재 칸에서 탐색한 방향의 수
24 |
25 | while (1) {
26 | //왼쪽으로 회전
27 | d = d === 0 ? 3 : d - 1;
28 | let nx = x + DIR[d][0];
29 | let ny = y + DIR[d][1];
30 |
31 | //정면에 가보지 않은 칸이 존재하는 경우 전진
32 | if (!map[nx][ny] && !visited[nx][ny]) {
33 | visited[nx][ny] = true;
34 | x = nx;
35 | y = ny;
36 | count++;
37 | turnTime = 0;
38 | continue;
39 | } else {
40 | //정면에 가보지 않은 칸이 없거나 바다인 경우
41 | turnTime++;
42 | }
43 |
44 | //네 방향 모두 갈 수 없는 경우
45 | if (turnTime === 4) {
46 | nx = x - DIR[d][0];
47 | ny = y - DIR[d][1];
48 |
49 | //뒤로 갈 수 있으면 이동
50 | if (!map[nx][ny]) {
51 | x = nx;
52 | y = ny;
53 | turnTime = 0;
54 | } else {
55 | //뒤가 바다로 막혀있는 경우
56 | break;
57 | }
58 | }
59 | }
60 |
61 | return count;
62 | }
63 |
64 | console.log(solution(n, m, x, y, d, map));
65 |
--------------------------------------------------------------------------------
/CHAPTER_04_구현/예제_4-1_상하좌우.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr] = input;
5 | n = Number(n);
6 | arr = arr.split(' ');
7 |
8 | function solution(n, arr) {
9 | const DIR = {
10 | L: [0, -1],
11 | R: [0, 1],
12 | U: [-1, 0],
13 | D: [1, 0],
14 | };
15 |
16 | let point = [1, 1];
17 | for (const d of arr) {
18 | const [x, y] = DIR[d];
19 |
20 | const nx = point[0] + x;
21 | const ny = point[1] + y;
22 |
23 | if (nx < 1 || nx > n || ny < 1 || ny > n) continue;
24 |
25 | point[0] = nx;
26 | point[1] = ny;
27 | }
28 |
29 | return point;
30 | }
31 |
32 | console.log(solution(n, arr));
33 |
--------------------------------------------------------------------------------
/CHAPTER_04_구현/예제_4-2_시각.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim();
3 |
4 | let n = Number(input);
5 |
6 | function solution(n) {
7 | let count = 0;
8 |
9 | for (let h = 0; h <= n; h++) {
10 | for (let m = 0; m <= 59; m++) {
11 | for (let s = 0; s <= 59; s++) {
12 | const time = `${h}${m}${s}`;
13 | if (time.includes('3')) {
14 | count++;
15 | }
16 | }
17 | }
18 | }
19 |
20 | return count;
21 | }
22 |
23 | console.log(solution(n));
24 |
--------------------------------------------------------------------------------
/CHAPTER_04_구현/왕실의나이트.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim();
3 |
4 | const x = input.charCodeAt(0) - 97 + 1;
5 | const y = +input[1];
6 |
7 | function solution(x, y) {
8 | const DIR = [
9 | [-1, -2],
10 | [1, -2],
11 | [2, -1],
12 | [2, 1],
13 | [1, 2],
14 | [-1, 2],
15 | [-2, 1],
16 | [-2, -1],
17 | ];
18 |
19 | let count = 0;
20 | for (let i = 0; i < 8; i++) {
21 | const nx = x + DIR[i][0];
22 | const ny = y + DIR[i][1];
23 |
24 | if (nx < 1 || nx > 8 || ny < 1 || ny > 8) continue;
25 |
26 | count++;
27 | }
28 |
29 | return count;
30 | }
31 |
32 | console.log(solution(x, y));
33 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/미로탈출.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | const [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | const graph = arr.map((v1) => v1.split('').map((v2) => +v2));
7 |
8 | const dir = [
9 | [0, 1],
10 | [0, -1],
11 | [1, 0],
12 | [-1, 0],
13 | ];
14 | const visited = Array.from(Array(n), () => Array(m).fill(false));
15 |
16 | const bfs = (graph, sx, sy) => {
17 | const q = [];
18 | q.push([sx, sy]);
19 | visited[sx][sy] = true;
20 |
21 | while (q.length !== 0) {
22 | const [x, y] = q.shift();
23 |
24 | for (let i = 0; i < 4; i++) {
25 | const nx = x + dir[i][0];
26 | const ny = y + dir[i][1];
27 |
28 | if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
29 |
30 | if (!visited[nx][ny] && graph[nx][ny]) {
31 | q.push([nx, ny]);
32 | visited[nx][ny] = true;
33 | graph[nx][ny] = graph[x][y] + 1;
34 | }
35 | }
36 | }
37 | };
38 |
39 | function solution(n, m, graph) {
40 | bfs(graph, 0, 0);
41 | return graph[n - 1][m - 1];
42 | }
43 |
44 | console.log(solution(n, m, graph));
45 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/미로탈출_NO방문처리.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | const [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | const graph = arr.map((v1) => v1.split('').map((v2) => +v2));
7 |
8 | const dir = [
9 | [0, 1],
10 | [0, -1],
11 | [1, 0],
12 | [-1, 0],
13 | ];
14 |
15 | const bfs = (graph, sx, sy) => {
16 | const q = [];
17 | q.push([sx, sy]);
18 |
19 | while (q.length !== 0) {
20 | const [x, y] = q.shift();
21 |
22 | for (let i = 0; i < 4; i++) {
23 | const nx = x + dir[i][0];
24 | const ny = y + dir[i][1];
25 |
26 | if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
27 |
28 | // 해당 노드를 처음 방문하는 경우에만 최단 거리 기록
29 | if (graph[nx][ny] === 1) {
30 | q.push([nx, ny]);
31 | graph[nx][ny] = graph[x][y] + 1;
32 | }
33 | }
34 | }
35 | };
36 |
37 | function solution(n, m, graph) {
38 | bfs(graph, 0, 0);
39 | console.log(graph);
40 | return graph[n - 1][m - 1];
41 | }
42 |
43 | console.log(solution(n, m, graph));
44 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-1_스택.js:
--------------------------------------------------------------------------------
1 | const stack = [];
2 |
3 | stack.push(5);
4 | stack.push(2);
5 | stack.push(3);
6 | stack.push(7);
7 | stack.pop();
8 | stack.push(1);
9 | stack.push(4);
10 | stack.pop();
11 |
12 | console.log(stack);
13 | console.log(stack.reverse());
14 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-2_큐.js:
--------------------------------------------------------------------------------
1 | const queue = [];
2 |
3 | queue.push(5);
4 | queue.push(2);
5 | queue.push(3);
6 | queue.push(7);
7 | queue.shift();
8 | queue.push(1);
9 | queue.push(4);
10 | queue.shift();
11 |
12 | console.log(queue);
13 | console.log(queue.reverse());
14 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-3_재귀 함수.js:
--------------------------------------------------------------------------------
1 | const recursive = () => {
2 | console.log('재귀 함수를 호출합니다.');
3 | recursive();
4 | };
5 |
6 | recursive();
7 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-4_재귀 함수 종료.js:
--------------------------------------------------------------------------------
1 | const recursive = (i) => {
2 | if (i === 10) return;
3 |
4 | console.log(`${i}번째 재귀 함수에서 ${i + 1}번째 재귀 함수를 호출합니다.`);
5 | recursive(i + 1);
6 | console.log(`${i}번째 재귀 함수를 종료합니다.`);
7 | };
8 |
9 | recursive(1);
10 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-5_2가지 방식으로 구현한 팩토리얼.js:
--------------------------------------------------------------------------------
1 | const factorialIterative = (n) => {
2 | let result = 1;
3 | for (let i = 2; i <= n; i++) {
4 | result *= i;
5 | }
6 | return result;
7 | };
8 |
9 | const factorialRecursive = (n) => {
10 | if (n < 2) return 1;
11 | return n * factorialRecursive(n - 1);
12 | };
13 |
14 | console.log(factorialIterative(5));
15 | console.log(factorialRecursive(5));
16 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-6_인접 행렬 방식.js:
--------------------------------------------------------------------------------
1 | const INF = Infinity;
2 |
3 | const graph = [
4 | [0, 7, 5],
5 | [7, 0, INF],
6 | [5, INF, 0],
7 | ];
8 |
9 | console.log(graph);
10 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-7_인접 리스트 방식.js:
--------------------------------------------------------------------------------
1 | const graph = Array.from(Array(3), () => []);
2 |
3 | //[노드, 거리] 형식으로 저장
4 | graph[0].push([1, 7]);
5 | graph[0].push([2, 5]);
6 |
7 | graph[1].push([0, 7]);
8 |
9 | graph[2].push([0, 5]);
10 |
11 | console.log(graph);
12 |
13 | //or
14 | const graph2 = [
15 | [
16 | [1, 7],
17 | [2, 5],
18 | ],
19 | [[0, 7]],
20 | [[0, 5]],
21 | ];
22 |
23 | //객체로도 표현 가능
24 | const graph3 = {
25 | 0: [
26 | [1, 7],
27 | [2, 5],
28 | ],
29 | 1: [[0, 7]],
30 | 2: [[0, 5]],
31 | };
32 |
33 | const graph4 = {
34 | A: ['B', 'C'],
35 | B: ['A'],
36 | C: ['A'],
37 | };
38 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-8_DFS.js:
--------------------------------------------------------------------------------
1 | const dfs = (graph, v, visited) => {
2 | //1. 탐색 시작 노드 방문 처리
3 | visited[v] = true;
4 | console.log(v);
5 |
6 | //2. 탐색 노드의 인접 노드 확인
7 | for (const cur of graph[v]) {
8 | if (!visited[cur]) {
9 | dfs(graph, cur, visited);
10 | }
11 | }
12 | };
13 |
14 | let graph = [
15 | [],
16 | [2, 3, 8],
17 | [1, 7],
18 | [1, 4, 5],
19 | [3, 5],
20 | [3, 4],
21 | [7],
22 | [2, 6, 8],
23 | [1, 7],
24 | ];
25 |
26 | let visited = [...Array(9).fill(false)];
27 |
28 | dfs(graph, 1, visited);
29 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/예제_5-9_BFS.js:
--------------------------------------------------------------------------------
1 | const bfs = (graph, start, visited) => {
2 | //1. 탐색 시작 노드 큐에 넣고 방문 처리
3 | const q = new Queue(); //연결 리스트로 구현한 큐 사용
4 | q.enqueue(start);
5 | visited[start] = true;
6 |
7 | while (!q.empty()) {
8 | const v = q.dequeue();
9 | console.log(v);
10 |
11 | //2. 탐색 노드의 인접 노드 확인
12 | for (const cur of graph[v]) {
13 | if (!visited[cur]) {
14 | q.enqueue(cur);
15 | visited[cur] = true;
16 | }
17 | }
18 | }
19 | };
20 |
21 | let graph = [
22 | [],
23 | [2, 3, 8],
24 | [1, 7],
25 | [1, 4, 5],
26 | [3, 5],
27 | [3, 4],
28 | [7],
29 | [2, 6, 8],
30 | [1, 7],
31 | ];
32 |
33 | let visited = [...Array(9).fill(false)];
34 |
35 | bfs(graph, 1, visited);
36 |
37 | //추가) 배열 큐 사용
38 | const bfs2 = (graph, start, visited) => {
39 | const q = [];
40 | q.push(start);
41 | visited[start] = true;
42 |
43 | while (q.length !== 0) {
44 | const v = q.shift();
45 | console.log(v);
46 |
47 | for (const cur of graph[v]) {
48 | if (!visited[cur]) {
49 | q.push(cur);
50 | visited[cur] = true;
51 | }
52 | }
53 | }
54 | };
55 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/음료수얼려먹기_BFS.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | const [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | const graph = arr.map((v1) => v1.split(''));
7 |
8 | const dir = [
9 | [0, 1],
10 | [0, -1],
11 | [1, 0],
12 | [-1, 0],
13 | ];
14 | const visited = Array.from(Array(n), () => Array(m).fill(false));
15 |
16 | const bfs = (graph, sx, sy) => {
17 | const q = [];
18 | q.push([sx, sy]);
19 | visited[sx][sy] = true;
20 |
21 | while (q.length !== 0) {
22 | const [x, y] = q.shift();
23 |
24 | for (let i = 0; i < 4; i++) {
25 | const nx = x + dir[i][0];
26 | const ny = y + dir[i][1];
27 |
28 | if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
29 |
30 | if (!visited[nx][ny] && graph[nx][ny] === '0') {
31 | q.push([nx, ny]);
32 | visited[nx][ny] = true;
33 | }
34 | }
35 | }
36 | };
37 |
38 | function solution(n, m, graph) {
39 | let count = 0;
40 |
41 | for (let i = 0; i < n; i++) {
42 | for (let j = 0; j < m; j++) {
43 | const cur = graph[i][j];
44 | if (!visited[i][j] && cur === '0') {
45 | bfs(graph, i, j);
46 | count++;
47 | }
48 | }
49 | }
50 |
51 | return count;
52 | }
53 |
54 | console.log(solution(n, m, graph));
55 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/음료수얼려먹기_DFS.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | const [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | const graph = arr.map((v1) => v1.split(''));
7 |
8 | const dir = [
9 | [0, 1],
10 | [0, -1],
11 | [1, 0],
12 | [-1, 0],
13 | ];
14 | const visited = Array.from(Array(n), () => Array(m).fill(false));
15 |
16 | const dfs = (graph, x, y) => {
17 | visited[x][y] = true;
18 |
19 | for (let i = 0; i < 4; i++) {
20 | const nx = x + dir[i][0];
21 | const ny = y + dir[i][1];
22 |
23 | if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
24 |
25 | if (!visited[nx][ny] && graph[nx][ny] === '0') {
26 | dfs(graph, nx, ny);
27 | }
28 | }
29 | };
30 |
31 | function solution(n, m, graph) {
32 | let count = 0;
33 |
34 | for (let i = 0; i < n; i++) {
35 | for (let j = 0; j < m; j++) {
36 | const cur = graph[i][j];
37 | if (!visited[i][j] && cur === '0') {
38 | dfs(graph, i, j);
39 | count++;
40 | }
41 | }
42 | }
43 |
44 | return count;
45 | }
46 |
47 | console.log(solution(n, m, graph));
48 |
--------------------------------------------------------------------------------
/CHAPTER_05_DFSBFS/추가_연결 리스트 큐.js:
--------------------------------------------------------------------------------
1 | class Node {
2 | constructor(data) {
3 | this.data = data;
4 | this.next = null;
5 | }
6 | }
7 |
8 | class Queue {
9 | constructor() {
10 | this.front = null;
11 | this.rear = null;
12 | this.size = 0;
13 | }
14 |
15 | isEmpty() {
16 | return this.size === 0;
17 | }
18 |
19 | enqueue(data) {
20 | const newNode = new Node(data);
21 | if (this.isEmpty()) this.front = newNode;
22 | else this.rear.next = newNode;
23 | this.rear = newNode;
24 | this.size++;
25 | }
26 |
27 | dequeue() {
28 | if (this.isEmpty()) return;
29 | const data = this.front.data;
30 | this.front = this.front.next;
31 | this.size--;
32 | return data;
33 | }
34 | }
35 |
36 | const q = new Queue();
37 | q.enqueue(5);
38 | q.enqueue(2);
39 | q.enqueue(3);
40 | q.enqueue(7);
41 | q.dequeue();
42 | q.enqueue(1);
43 | q.enqueue(4);
44 | q.dequeue();
45 |
46 | console.log(q);
47 |
--------------------------------------------------------------------------------
/CHAPTER_06_정렬/두 배열의 원소 교체.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nk, A, B] = input;
5 | const [n, k] = nk.split(' ');
6 | A = A.replace('\r', '')
7 | .split(' ')
8 | .map((v) => +v);
9 | B = B.replace('\r', '')
10 | .split(' ')
11 | .map((v) => +v);
12 |
13 | function solution(n, k, A, B) {
14 | A.sort((a, b) => a - b);
15 | B.sort((a, b) => b - a);
16 |
17 | for (let i = 0; i < k; i++) {
18 | if (A[i] < B[i]) {
19 | [A[i], B[i]] = [B[i], A[i]];
20 | }
21 | }
22 |
23 | return A.reduce((a, b) => a + b);
24 | }
25 |
26 | console.log(solution(n, k, A, B));
27 |
--------------------------------------------------------------------------------
/CHAPTER_06_정렬/성적이 낮은 순서로 학생 출력하기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, ...arr] = input;
5 | const students = arr.map((v) => v.replace('\r', '').split(' '));
6 |
7 | function solution(n, students) {
8 | const sortedNames = students
9 | .sort((a, b) => a[1] - b[1])
10 | .map((student) => student[0]);
11 |
12 | return sortedNames.join(' ');
13 | }
14 |
15 | console.log(solution(n, students));
16 |
--------------------------------------------------------------------------------
/CHAPTER_06_정렬/예제_6-1_선택 정렬.js:
--------------------------------------------------------------------------------
1 | let array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8];
2 |
3 | for (let i = 0; i < array.length; i++) {
4 | let minIdx = i;
5 | for (let j = i + 1; j < array.length; j++) {
6 | if (array[minIdx] > array[j]) {
7 | minIdx = j;
8 | }
9 | }
10 | [array[i], array[minIdx]] = [array[minIdx], array[i]];
11 | }
12 |
13 | console.log(array);
14 |
--------------------------------------------------------------------------------
/CHAPTER_06_정렬/예제_6-2_삽입 정렬.js:
--------------------------------------------------------------------------------
1 | let array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8];
2 |
3 | for (let i = 1; i < array.length; i++) {
4 | for (let j = i; j > 0; j--) {
5 | if (array[j - 1] < array[j]) break;
6 | [array[j], array[j - 1]] = [array[j - 1], array[j]];
7 | }
8 | }
9 |
10 | console.log(array);
11 |
--------------------------------------------------------------------------------
/CHAPTER_06_정렬/예제_6-3_퀵 정렬.js:
--------------------------------------------------------------------------------
1 | let arr = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8];
2 | const n = arr.length;
3 |
4 | const quickSort = (arr, start, end) => {
5 | if (start >= end) return;
6 |
7 | const p = start;
8 | let left = start + 1;
9 | let right = end;
10 |
11 | while (left <= right) {
12 | //피벗보다 큰 데이터 찾을 때까지 탐색
13 | while (left <= end && arr[p] >= arr[left]) {
14 | left++;
15 | }
16 | //피벗보다 작은 데이터 찾을 때까지 탐색
17 | while (right > start && arr[p] <= arr[right]) {
18 | right--;
19 | }
20 |
21 | //swap
22 | if (left > right) {
23 | [arr[p], arr[right]] = [arr[right], arr[p]];
24 | } else {
25 | [arr[left], arr[right]] = [arr[right], arr[left]];
26 | }
27 | }
28 |
29 | quickSort(arr, start, right - 1);
30 | quickSort(arr, right + 1, end);
31 | };
32 |
33 | quickSort(arr, 0, n - 1);
34 | console.log(arr);
35 |
--------------------------------------------------------------------------------
/CHAPTER_06_정렬/예제_6-4.자바스크립트의 장점을 살린 퀵 정렬.js:
--------------------------------------------------------------------------------
1 | let arr = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8];
2 | const n = arr.length;
3 |
4 | const quickSort = (arr) => {
5 | if (arr.length <= 1) return arr;
6 |
7 | const p = arr[0]; //피벗은 첫 번째 원소
8 | const tail = arr.slice(1); //피벗을 제외한 배열
9 |
10 | const leftArr = tail.filter((v) => v <= p); //분할된 왼쪽 부분 (피벗보다 작은 값)
11 | const rightArr = tail.filter((v) => v > p); //분할된 오른쪽 부분 (피벗보다 큰 값)
12 |
13 | return [...quickSort(leftArr), p, ...quickSort(rightArr)];
14 | };
15 |
16 | console.log(quickSort(arr, 0, n - 1));
17 |
--------------------------------------------------------------------------------
/CHAPTER_06_정렬/예제_6-5.계수 정렬.js:
--------------------------------------------------------------------------------
1 | const arr = [7, 5, 9, 0, 3, 1, 6, 2, 9, 1, 4, 8, 0, 5, 2];
2 |
3 | const count = [...Array(Math.max(...arr) + 1).fill(0)];
4 |
5 | arr.forEach((num) => count[num]++);
6 |
7 | let sorted = '';
8 | for (let num = 0; num < count.length; num++)
9 | sorted += num.toString().repeat(count[num]);
10 | console.log([...sorted]);
11 |
--------------------------------------------------------------------------------
/CHAPTER_06_정렬/위에서 아래로.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, ...arr] = input;
5 | arr = arr.map((v) => +v.replace('\r', ''));
6 |
7 | function solution(n, arr) {
8 | return arr.sort((a, b) => b - a).join(' ');
9 | }
10 |
11 | console.log(solution(n, arr));
12 |
--------------------------------------------------------------------------------
/CHAPTER_07_이진탐색/떡볶이 떡 만들기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | arr = arr.split(' ').map((v) => +v);
7 |
8 | let ans = 0;
9 | const binarySearch = (arr, target, start, end) => {
10 | while (start <= end) {
11 | const mid = ~~((start + end) / 2); //현재 h
12 | const sum = arr.map((v) => (v < mid ? 0 : v - mid)).reduce((a, b) => a + b);
13 |
14 | if (target <= sum) {
15 | //필요한 떡의 길이보다 큰 경우
16 | start = mid + 1;
17 | ans = mid;
18 | } else {
19 | //필요한 떡의 길이보다 작은 경우
20 | end = mid - 1;
21 | }
22 | }
23 |
24 | return ans;
25 | };
26 |
27 | function solution(n, m, arr) {
28 | return binarySearch(arr, m, 0, Math.max(...arr));
29 | }
30 |
31 | console.log(solution(n, m, arr));
32 |
--------------------------------------------------------------------------------
/CHAPTER_07_이진탐색/부품 찾기_계수 정렬.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr, m, req] = input;
5 | n = +n;
6 | arr = arr.split(' ').map((v) => +v);
7 | m = +m;
8 | req = req.split(' ').map((v) => +v);
9 |
10 | function solution(n, m, arr, req) {
11 | let store = [...Array(Math.max(...arr) + 1).fill(false)];
12 | arr.forEach((v) => (store[v] = true));
13 |
14 | let ans = '';
15 | for (const target of req) {
16 | if (store[target]) ans += 'yes ';
17 | else ans += 'no ';
18 | }
19 | return ans;
20 | }
21 |
22 | console.log(solution(n, m, arr, req));
23 |
--------------------------------------------------------------------------------
/CHAPTER_07_이진탐색/부품 찾기_이진 탐색.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr, m, req] = input;
5 | n = +n;
6 | arr = arr.split(' ').map((v) => +v);
7 | m = +m;
8 | req = req.split(' ').map((v) => +v);
9 |
10 | const binarySearch = (arr, target, start, end) => {
11 | const sorted = arr.sort((a, b) => a - b);
12 |
13 | if (start > end) return -1;
14 |
15 | const mid = ~~((start + end) / 2);
16 | if (target === sorted[mid]) return mid;
17 | else if (target < sorted[mid])
18 | return binarySearch(arr, target, start, mid - 1);
19 | else return binarySearch(arr, target, mid + 1, end);
20 | };
21 |
22 | function solution(n, m, arr, req) {
23 | let ans = '';
24 | for (const target of req) {
25 | if (binarySearch(arr, target, 0, n - 1) !== -1) ans += 'yes ';
26 | else ans += 'no ';
27 | }
28 | return ans;
29 | }
30 |
31 | console.log(solution(n, m, arr, req));
32 |
--------------------------------------------------------------------------------
/CHAPTER_07_이진탐색/부품 찾기_집합.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr, m, req] = input;
5 | n = +n;
6 | arr = arr.split(' ').map((v) => +v);
7 | m = +m;
8 | req = req.split(' ').map((v) => +v);
9 |
10 | function solution(n, m, arr, req) {
11 | let store = new Set(arr);
12 |
13 | let ans = '';
14 | for (const target of req) {
15 | if (store.has(target)) ans += 'yes ';
16 | else ans += 'no ';
17 | }
18 | return ans;
19 | }
20 |
21 | console.log(solution(n, m, arr, req));
22 |
--------------------------------------------------------------------------------
/CHAPTER_07_이진탐색/예제_7-1_순차 탐색.js:
--------------------------------------------------------------------------------
1 | const sequentialSearch = (n, target, arr) => {
2 | for (let i = 0; i < n; i++) {
3 | if (target === arr[i]) return i + 1;
4 | }
5 | };
6 |
7 | const n = 5;
8 | const target = 'Dongbin';
9 | const arr = ['Haneul', 'Jonggu', 'Dongbin', 'Taeil', 'Sangwook'];
10 |
11 | console.log(sequentialSearch(n, target, arr));
12 |
--------------------------------------------------------------------------------
/CHAPTER_07_이진탐색/예제_7-2_재귀 함수로 구현한 이진 탐색.js:
--------------------------------------------------------------------------------
1 | const binarySearch = (arr, target, start, end) => {
2 | if (start > end) return -1; //원소가 존재하지 않는 경우
3 |
4 | const mid = ~~((start + end) / 2);
5 | if (target === arr[mid]) return mid;
6 | else if (target < arr[mid]) return binarySearch(arr, target, start, mid - 1);
7 | else return binarySearch(arr, target, mid + 1, end);
8 | };
9 |
10 | const n = 10;
11 | const target = 7;
12 | const arr = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
13 |
14 | const start = 0,
15 | end = n - 1;
16 | console.log(binarySearch(arr, target, start, end) + 1);
17 |
--------------------------------------------------------------------------------
/CHAPTER_07_이진탐색/예제_7-3_반복문으로 구현한 이진 탐색.js:
--------------------------------------------------------------------------------
1 | const binarySearch = (arr, target, start, end) => {
2 | while (start <= end) {
3 | const mid = ~~((start + end) / 2);
4 | if (target === arr[mid]) return mid;
5 | else if (target < arr[mid]) end = mid - 1;
6 | else start = mid + 1;
7 | }
8 |
9 | return -1;
10 | };
11 |
12 | const n = 10;
13 | const target = 7;
14 | const arr = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
15 |
16 | const start = 0,
17 | end = n - 1;
18 | console.log(binarySearch(arr, target, start, end) + 1);
19 |
--------------------------------------------------------------------------------
/CHAPTER_08_다이나믹 프로그래밍/1로 만들기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim();
3 |
4 | const n = +input;
5 |
6 | const d = [...Array(n + 1).fill(0)];
7 |
8 | //1. top-down
9 | const dp = (x) => {
10 | if (x === 1 || x === 2 || x === 3 || x === 5) return 1;
11 |
12 | if (d[x] !== 0) return d[x];
13 |
14 | if (x % 5 === 0) return (d[x] = Math.min(dp(x / 5), dp(x - 1)) + 1);
15 | if (x % 3 === 0) return (d[x] = Math.min(dp(x / 3), dp(x - 1)) + 1);
16 | if (x % 2 === 0) return (d[x] = Math.min(dp(x / 2), dp(x - 1)) + 1);
17 | return (d[x] = dp(x - 1) + 1);
18 | };
19 |
20 | //2. bottom-up
21 | const dp2 = (x) => {
22 | d[1] = d[2] = d[3] = d[5] = 1;
23 | d[4] = 2;
24 |
25 | for (let i = 6; i <= x; i++) {
26 | d[i] = d[i - 1] + 1;
27 | if (i % 2 === 0) d[i] = Math.min(d[i / 2], d[i - 1]) + 1;
28 | if (i % 3 === 0) d[i] = Math.min(d[i / 3], d[i - 1]) + 1;
29 | if (i % 5 === 0) d[i] = Math.min(d[i / 5], d[i - 1]) + 1;
30 | }
31 |
32 | return d[x];
33 | };
34 |
35 | function solution(n) {
36 | return dp(n);
37 | }
38 |
39 | console.log(solution(n));
40 |
--------------------------------------------------------------------------------
/CHAPTER_08_다이나믹 프로그래밍/개미 전사.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr] = input;
5 | n = +n;
6 | arr = arr.split(' ').map((v) => +v);
7 |
8 | const d = [...Array(n + 1).fill(0)];
9 |
10 | const dp = (n) => {
11 | d[0] = arr[0];
12 | d[1] = Math.max(arr[0], arr[1]);
13 |
14 | for (let i = 2; i < n; i++) {
15 | d[i] = Math.max(d[i - 2] + arr[i], d[i - 1]);
16 | }
17 |
18 | return d[n - 1];
19 | };
20 |
21 | function solution(n, arr) {
22 | return dp(n);
23 | }
24 |
25 | console.log(solution(n, arr));
26 |
--------------------------------------------------------------------------------
/CHAPTER_08_다이나믹 프로그래밍/바닥 공사.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim();
3 |
4 | const n = +input;
5 |
6 | const DIV = 796796;
7 | const d = [...Array(n + 1).fill(0)];
8 |
9 | const dp = (n) => {
10 | d[1] = 1;
11 | d[2] = 3;
12 |
13 | for (let i = 3; i <= n; i++) {
14 | d[i] = (d[i - 2] * 2 + d[i - 1]) % DIV;
15 | }
16 |
17 | return d[n];
18 | };
19 |
20 | function solution(n) {
21 | return dp(n);
22 | }
23 |
24 | console.log(solution(n));
25 |
--------------------------------------------------------------------------------
/CHAPTER_08_다이나믹 프로그래밍/예제_8-1_피보나치 함수.js:
--------------------------------------------------------------------------------
1 | const fibo = (x) => {
2 | if (x === 1 || x === 2) return 1;
3 | return fibo(x - 1) + fibo(x - 2);
4 | };
5 |
6 | console.log(fibo(4));
7 |
--------------------------------------------------------------------------------
/CHAPTER_08_다이나믹 프로그래밍/예제_8-2_피보나치 수열 (재귀적).js:
--------------------------------------------------------------------------------
1 | let d = [...Array(100).fill(0)];
2 |
3 | const fibo = (x) => {
4 | if (x === 1 || x === 2) return 1;
5 |
6 | if (d[x] != 0) return d[x];
7 | return (d[x] = fibo(x - 1) + fibo(x - 2));
8 | };
9 |
10 | console.log(fibo(4));
11 |
--------------------------------------------------------------------------------
/CHAPTER_08_다이나믹 프로그래밍/예제_8-3_호출되는 함수 확인.js:
--------------------------------------------------------------------------------
1 | let d = [...Array(100).fill(0)];
2 |
3 | const fibo = (x) => {
4 | console.log(`f(${x})`);
5 | if (x === 1 || x === 2) return 1;
6 |
7 | if (d[x] != 0) return d[x];
8 | return (d[x] = fibo(x - 1) + fibo(x - 2));
9 | };
10 |
11 | fibo(6);
12 |
--------------------------------------------------------------------------------
/CHAPTER_08_다이나믹 프로그래밍/예제_8-4_피보나치 수열 (반복적).js:
--------------------------------------------------------------------------------
1 | const n = 99;
2 | let d = [...Array(n + 1).fill(0)];
3 |
4 | const fibo = (x) => {
5 | d[1] = d[2] = 1;
6 |
7 | for (let i = 3; i <= n; i++) {
8 | d[i] = d[i - 1] + d[i - 2];
9 | }
10 | return d[x];
11 | };
12 |
13 | console.log(fibo(n));
14 |
--------------------------------------------------------------------------------
/CHAPTER_08_다이나믹 프로그래밍/효율적인 화폐 구성.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | const [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | const coins = arr.map((v) => +v);
7 |
8 | const d = [...Array(m + 1).fill(Infinity)];
9 |
10 | const dp = (n, m, coins) => {
11 | d[0] = 0;
12 | for (const coin of coins) d[coin] = 1;
13 |
14 | for (let i = 1; i <= m; i++) {
15 | for (const coin of coins) {
16 | if (i < coin) continue;
17 | d[i] = Math.min(d[i], d[i - coin]) + 1;
18 | }
19 | }
20 |
21 | return d[m];
22 | };
23 |
24 | function solution(n, m, coins) {
25 | const result = dp(n, m, coins);
26 | return result === Infinity ? -1 : result;
27 | }
28 |
29 | console.log(solution(n, m, coins));
30 |
--------------------------------------------------------------------------------
/CHAPTER_09_최단경로/PriorityQueue.js:
--------------------------------------------------------------------------------
1 | //최소힙
2 | class PriorityQueue {
3 | constructor() {
4 | this.heap = [];
5 | }
6 |
7 | empty() {
8 | return this.heap.length === 0;
9 | }
10 |
11 | peek() {
12 | return this.heap[0];
13 | }
14 |
15 | push(data) {
16 | this.heap.push(data);
17 |
18 | let i = this.heap.length - 1;
19 | while (i > 0) {
20 | const parent = ~~((i - 1) / 2);
21 | if (this.heap[parent] <= this.heap[i]) break;
22 | [this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];
23 | i = parent;
24 | }
25 | }
26 |
27 | pop() {
28 | if (this.empty()) return;
29 |
30 | const value = this.peek();
31 | [this.heap[0], this.heap[this.heap.length - 1]] = [
32 | this.heap[this.heap.length - 1],
33 | this.heap[0],
34 | ];
35 | this.heap.pop();
36 | this._heapify();
37 | return value;
38 | }
39 |
40 | _heapify() {
41 | const x = this.peek();
42 | const n = this.heap.length;
43 | let cur = 0;
44 |
45 | while (2 * cur + 1 < n) {
46 | const leftChild = 2 * cur + 1;
47 | const rightChild = leftChild + 1;
48 | const smallerChild =
49 | rightChild < n && this.heap[rightChild] < this.heap[leftChild]
50 | ? rightChild
51 | : leftChild;
52 |
53 | //루트 노드의 값이 더 큰 경우 swap
54 | if (x > this.heap[smallerChild]) {
55 | [this.heap[cur], this.heap[smallerChild]] = [
56 | this.heap[smallerChild],
57 | this.heap[cur],
58 | ];
59 | cur = smallerChild;
60 | } else {
61 | break;
62 | }
63 | }
64 | }
65 | }
66 |
67 | const pq = new PriorityQueue();
68 | pq.push(3);
69 | pq.push(5);
70 | pq.push(2);
71 | pq.pop();
72 | pq.push(6);
73 | pq.push(1);
74 | pq.pop();
75 |
76 | while (!pq.empty()) {
77 | console.log(pq.pop());
78 | }
79 |
--------------------------------------------------------------------------------
/CHAPTER_09_최단경로/미래 도시.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | let [x, k] = arr[m].split(' ').map((v) => +v);
7 | arr.pop();
8 | arr = arr.map((str) => str.split(' ').map((v) => +v));
9 |
10 | function solution(n, m, x, k, arr) {
11 | const d = Array.from(Array(n + 1), () => Array(n + 1).fill(Infinity));
12 | for (let i = 1; i <= n; i++) d[i][i] = 0;
13 | for (const value of arr) {
14 | const [u, v] = value;
15 | d[u][v] = 1;
16 | d[v][u] = 1;
17 | }
18 |
19 | for (let i = 1; i <= n; i++) {
20 | for (let from = 1; from <= n; from++) {
21 | for (let to = 1; to <= n; to++) {
22 | if (i === from || from === to) continue;
23 | d[from][to] = Math.min(d[from][to], d[from][i] + d[i][to]);
24 | }
25 | }
26 | }
27 |
28 | const dist = d[1][k] + d[k][x];
29 | return dist >= Infinity ? -1 : dist;
30 | }
31 |
32 | console.log(solution(n, m, x, k, arr));
33 |
--------------------------------------------------------------------------------
/CHAPTER_09_최단경로/예제_9-1_간단한 다익스트라.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, s, ...rest] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | const start = +s;
7 | const arr = rest.map((str) => str.split(' ').map((v) => +v));
8 |
9 | let visited = [...Array(n + 1).fill(false)];
10 | let d = [...Array(n + 1).fill(Infinity)];
11 |
12 | function solution(n, m, start, arr) {
13 | //초기화
14 | const graph = Array.from(Array(n + 1), () => []);
15 | for (const v of arr) {
16 | const [a, b, c] = v;
17 | graph[a].push([b, c]);
18 | }
19 |
20 | //방문하지 않은 노드에서 최단 거리가 가장 짧은 노드의 인덱스 반환
21 | const getSmallestNode = () => {
22 | let min = Infinity;
23 | let index = 0;
24 | for (const i in d) {
25 | if (!visited[i] && min > d[i]) {
26 | min = d[i];
27 | index = i;
28 | }
29 | }
30 | return index;
31 | };
32 |
33 | const dijkstra = (start) => {
34 | //시작 노드 초기화
35 | d[start] = 0;
36 | visited[start] = true;
37 | for (const i of graph[start]) {
38 | const [node, cost] = i;
39 | d[node] = cost;
40 | }
41 |
42 | //시작 노드를 제외한 전체 노드에 대해 반복
43 | for (let i = 0; i < n; i++) {
44 | const cur = +getSmallestNode();
45 | visited[cur] = true;
46 |
47 | for (const j of graph[cur]) {
48 | const node = j[0];
49 | const cost = d[cur] + j[1];
50 | if (cost < d[node]) {
51 | d[node] = cost;
52 | }
53 | }
54 | }
55 | };
56 |
57 | dijkstra(start);
58 |
59 | for (let i = 1; i <= n; i++) {
60 | if (d[i] === Infinity) {
61 | console.log('INFINITY');
62 | } else {
63 | console.log(d[i]);
64 | }
65 | }
66 |
67 | return d;
68 | }
69 |
70 | console.log(solution(n, m, start, arr));
71 |
--------------------------------------------------------------------------------
/CHAPTER_09_최단경로/예제_9-2_개선된 다익스트라.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, s, ...rest] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | const start = +s;
7 | const arr = rest.map((str) => str.split(' ').map((v) => +v));
8 |
9 | let d = [...Array(n + 1).fill(Infinity)];
10 |
11 | function solution(n, m, start, arr) {
12 | //초기화
13 | const graph = Array.from(Array(n + 1), () => []);
14 | for (const v of arr) {
15 | const [a, b, c] = v;
16 | graph[a].push([b, c]);
17 | }
18 |
19 | const dijkstra = (start) => {
20 | //시작 노드 초기화
21 | const pq = new PriorityQueue();
22 | pq.push([0, start]); //[거리, 노드]
23 | d[start] = 0;
24 |
25 | while (!pq.empty()) {
26 | const [dist, cur] = pq.pop(); //현재 최단 거리가 가장 짧은 노드의 정보
27 |
28 | //방문한 적이 있는 경우(최단 거리가 아닌 경우) 스킵
29 | if (d[cur] < dist) continue;
30 |
31 | for (const i of graph[cur]) {
32 | const node = i[0];
33 | const cost = dist + i[1];
34 | if (cost < d[node]) {
35 | pq.push([cost, node]);
36 | d[node] = cost;
37 | }
38 | }
39 | }
40 | };
41 |
42 | dijkstra(start);
43 |
44 | for (let i = 1; i <= n; i++) {
45 | if (d[i] === Infinity) {
46 | console.log('INFINITY');
47 | } else {
48 | console.log(d[i]);
49 | }
50 | }
51 |
52 | return d;
53 | }
54 |
55 | console.log(solution(n, m, start, arr));
56 |
--------------------------------------------------------------------------------
/CHAPTER_09_최단경로/예제_9-3_플로이드 워셜.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, m, ...rest] = input;
5 | (n = +n), (m = +m);
6 | const arr = rest.map((str) => str.split(' ').map((v) => +v));
7 |
8 | function solution(n, m, arr) {
9 | let d = Array.from(Array(n + 1), () => Array(n + 1).fill(Infinity));
10 | for (let i = 1; i <= n; i++) d[i][i] = 0;
11 | for (const value of arr) {
12 | const [u, v, cost] = value;
13 | d[u][v] = cost;
14 | }
15 |
16 | for (let k = 1; k <= n; k++) {
17 | for (let from = 1; from <= n; from++) {
18 | for (let to = 1; to <= n; to++) {
19 | if (k === from || from === to) continue; //생략 가능
20 | d[from][to] = Math.min(d[from][to], d[from][k] + d[k][to]);
21 | }
22 | }
23 | }
24 |
25 | let ans = '';
26 | for (let from = 1; from <= n; from++) {
27 | for (let to = 1; to <= n; to++) {
28 | if (d[from][to] === Infinity) ans += 'INFINITY';
29 | else ans += `${d[from][to]} `;
30 | }
31 | ans += '\n';
32 | }
33 |
34 | return ans;
35 | }
36 |
37 | console.log(solution(n, m, arr));
38 |
--------------------------------------------------------------------------------
/CHAPTER_09_최단경로/전보.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nmc, ...arr] = input;
5 | const [n, m, c] = nmc.split(' ').map((v) => +v);
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | let d = [...Array(n + 1).fill(Infinity)];
9 | function solution(n, m, c, arr) {
10 | let graph = Array.from(Array(n + 1), () => []);
11 | for (const value of arr) {
12 | const [u, v, dist] = value;
13 | graph[u].push([v, dist]);
14 | }
15 |
16 | const pq = new PriorityQueue();
17 | pq.push([0, c]);
18 | d[c] = 0;
19 |
20 | while (!pq.empty()) {
21 | const [dist, cur] = pq.pop();
22 |
23 | if (d[cur] < dist) continue;
24 |
25 | for (const i of graph[cur]) {
26 | const node = i[0];
27 | const cost = dist + i[1];
28 | if (cost < d[node]) {
29 | pq.push([cost, node]);
30 | d[node] = cost;
31 | }
32 | }
33 | }
34 |
35 | d = d.slice(1);
36 | const count = d.filter((v) => v && v !== Infinity).length;
37 | const max = Math.max(...d);
38 |
39 | return [count, max];
40 | }
41 |
42 | console.log(solution(n, m, c, arr));
43 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/도시 분할 계획.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | function solution(n, m, arr) {
9 | const findParent = (parent, x) => {
10 | if (parent[x] === x) return parent[x];
11 | else return (parent[x] = findParent(parent, parent[x]));
12 | };
13 |
14 | const unionParent = (parent, a, b) => {
15 | a = findParent(parent, a);
16 | b = findParent(parent, b);
17 | if (a < b) parent[b] = a;
18 | else parent[a] = b;
19 | };
20 |
21 | let parent = [...Array(n + 1).fill(0)];
22 | for (let i = 1; i <= n; i++) {
23 | parent[i] = i;
24 | }
25 |
26 | let edges = [];
27 | for (const value of arr) {
28 | const [u, v, cost] = value;
29 | edges.push([cost, u, v]);
30 | }
31 |
32 | edges.sort((a, b) => a[0] - b[0]);
33 |
34 | let total = 0;
35 | let last = 0;
36 | for (const edge of edges) {
37 | const [cost, u, v] = edge;
38 | if (findParent(parent, u) !== findParent(parent, v)) {
39 | unionParent(parent, u, v);
40 | total += cost;
41 | last = cost;
42 | }
43 | }
44 |
45 | return total - last;
46 | }
47 |
48 | console.log(solution(n, m, arr));
49 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/예제_10-1_기본적인 서로소 집합.js:
--------------------------------------------------------------------------------
1 | //특정 원소가 속한 집합 찾기 (루트 찾기)
2 | const findParent = (parent, x) => {
3 | if (parent[x] === x) return x;
4 | return findParent(parent, parent[x]);
5 | };
6 |
7 | //두 원소가 속한 집합을 합치기 (루트 갱신)
8 | const unionParent = (parent, a, b) => {
9 | a = findParent(parent, a);
10 | b = findParent(parent, b);
11 | if (a < b) parent[b] = a;
12 | else parent[a] = b;
13 | };
14 |
15 | const fs = require('fs');
16 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
17 |
18 | let [nm, ...arr] = input;
19 | const [n, m] = nm.split(' ').map((v) => +v);
20 | const edges = arr.map((str) => str.split(' ').map((v) => +v));
21 |
22 | function solution(n, m, edges) {
23 | //부모 테이블 초기화
24 | let parent = [...Array(n + 1).fill(0)];
25 | for (let i = 1; i <= n; i++) {
26 | parent[i] = i;
27 | }
28 |
29 | //union 연산 수행
30 | for (const edge of edges) {
31 | const [a, b] = edge;
32 | unionParent(parent, a, b);
33 | }
34 |
35 | //각 원소가 속한 집합 출력
36 | let sets = '';
37 | for (let i = 1; i <= n; i++) {
38 | sets += findParent(parent, i);
39 | }
40 |
41 | console.log(`각 원소가 속한 집합: ${sets.split('').join(' ')}`);
42 | console.log(`부모 테이블: ${parent.slice(1, n).join(' ')}`);
43 | }
44 |
45 | solution(n, m, edges);
46 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/예제_10-2_경로 압축 기법.js:
--------------------------------------------------------------------------------
1 | const findParent = (parent, x) => {
2 | if (parent[x] === x) return parent[x];
3 | return (parent[x] = findParent(parent, parent[x]));
4 | };
5 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/예제_10-3_개선된 서로소 집합.js:
--------------------------------------------------------------------------------
1 | //특정 원소가 속한 집합 찾기 (루트 찾기)
2 | const findParent = (parent, x) => {
3 | if (parent[x] === x) return parent[x];
4 | return (parent[x] = findParent(parent, parent[x]));
5 | };
6 |
7 | //두 원소가 속한 집합을 합치기 (루트 갱신)
8 | const unionParent = (parent, a, b) => {
9 | a = findParent(parent, a);
10 | b = findParent(parent, b);
11 | if (a < b) parent[b] = a;
12 | else parent[a] = b;
13 | };
14 |
15 | const fs = require('fs');
16 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
17 |
18 | let [nm, ...arr] = input;
19 | const [n, m] = nm.split(' ').map((v) => +v);
20 | const edges = arr.map((str) => str.split(' ').map((v) => +v));
21 |
22 | function solution(n, m, edges) {
23 | //부모 테이블 초기화
24 | let parent = [...Array(n + 1).fill(0)];
25 | for (let i = 1; i <= n; i++) {
26 | parent[i] = i;
27 | }
28 |
29 | //union 연산 수행
30 | for (const edge of edges) {
31 | const [a, b] = edge;
32 | unionParent(parent, a, b);
33 | }
34 |
35 | //각 원소가 속한 집합 출력
36 | let sets = '';
37 | for (let i = 1; i <= n; i++) {
38 | sets += findParent(parent, i);
39 | }
40 |
41 | console.log(`각 원소가 속한 집합: ${sets.split('').join(' ')}`);
42 | console.log(`부모 테이블: ${parent.slice(1, n).join(' ')}`);
43 | }
44 |
45 | solution(n, m, edges);
46 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/예제_10-4_사이클 판별js:
--------------------------------------------------------------------------------
1 | //특정 원소가 속한 집합 찾기 (루트 찾기)
2 | const findParent = (parent, x) => {
3 | if (parent[x] === x) return parent[x];
4 | return (parent[x] = findParent(parent, parent[x]));
5 | };
6 |
7 | //두 원소가 속한 집합을 합치기 (루트 갱신)
8 | const unionParent = (parent, a, b) => {
9 | a = findParent(parent, a);
10 | b = findParent(parent, b);
11 | if (a < b) parent[b] = a;
12 | else parent[a] = b;
13 | };
14 |
15 | const fs = require('fs');
16 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
17 |
18 | let [nm, ...arr] = input;
19 | const [n, m] = nm.split(' ').map((v) => +v);
20 | const edges = arr.map((str) => str.split(' ').map((v) => +v));
21 |
22 | function solution(n, m, edges) {
23 | //부모 테이블 초기화
24 | let parent = [...Array(n + 1).fill(0)];
25 | for (let i = 1; i <= n; i++) {
26 | parent[i] = i;
27 | }
28 |
29 | let isCycle = false;
30 | for (const edge of edges) {
31 | const [a, b] = edge;
32 | if (findParent(parent, a) !== findParent(parent, b))
33 | unionParent(parent, a, b);
34 | else {
35 | isCycle = true;
36 | break;
37 | }
38 | }
39 |
40 | console.log(
41 | isCycle ? '사이클이 발생했습니다.' : '사이클이 발생하지 않았습니다.'
42 | );
43 | }
44 |
45 | solution(n, m, edges);
46 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/예제_10-5_크루스칼.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | const findParent = (parent, x) => {
9 | if (parent[x] === x) return parent[x];
10 | return (parent[x] = findParent(parent, parent[x]));
11 | };
12 |
13 | const unionParent = (parent, a, b) => {
14 | a = findParent(parent, a);
15 | b = findParent(parent, b);
16 | if (a < b) parent[b] = a;
17 | else parent[a] = b;
18 | };
19 |
20 | function solution(n, m, arr) {
21 | let parent = [...Array(n + 1).fill(0)];
22 | for (let i = 1; i <= n; i++) {
23 | parent[i] = i;
24 | }
25 |
26 | let edges = [];
27 | for (const value of arr) {
28 | const [u, v, cost] = value;
29 | edges.push([cost, u, v]);
30 | }
31 |
32 | edges.sort((a, b) => a[0] - b[0]);
33 |
34 | let result = 0;
35 | for (const edge of edges) {
36 | const [cost, a, b] = edge;
37 | if (findParent(parent, a) !== findParent(parent, b)) {
38 | unionParent(parent, a, b);
39 | result += cost;
40 | }
41 | }
42 |
43 | return result;
44 | }
45 |
46 | console.log(solution(n, m, arr));
47 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/예제_10-6_위상 정렬.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | let indegree = [...Array(n + 1).fill(0)];
9 | function solution(n, m, arr) {
10 | let graph = Array.from(Array(n + 1), () => []);
11 |
12 | for (const value of arr) {
13 | const [u, v] = value;
14 | graph[u].push(v);
15 | indegree[v]++;
16 | }
17 |
18 | const q = new Queue();
19 | for (let i = 1; i <= n; i++) {
20 | if (indegree[i] === 0) q.enqueue(i);
21 | }
22 |
23 | let sorted = [];
24 | while (!q.isEmpty()) {
25 | const cur = q.dequeue();
26 | sorted.push(cur);
27 |
28 | for (const node of graph[cur]) {
29 | indegree[node]--;
30 | if (indegree[node] === 0) q.enqueue(node);
31 | }
32 | }
33 |
34 | return sorted;
35 | }
36 |
37 | console.log(solution(n, m, arr));
38 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/커리큘럼.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, ...arr] = input;
5 | n = +n;
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | function solution(n, arr) {
9 | let indegree = [...Array(n + 1).fill(0)];
10 | let graph = Array.from(Array(n + 1), () => []);
11 | let times = [...Array(n + 1).fill(0)];
12 |
13 | for (let i = 0; i < arr.length; i++) {
14 | const [time, ...rest] = arr[i];
15 | for (let j = 0; j < rest.length - 1; j++) {
16 | graph[rest[j]].push(i + 1);
17 | }
18 | indegree[i + 1] = rest.length - 1;
19 | times[i + 1] = time;
20 | }
21 |
22 | let result = [];
23 |
24 | const q = new Queue();
25 | for (let i = 1; i <= n; i++) {
26 | if (indegree[i] === 0) {
27 | q.enqueue(i);
28 | result[i] = times[i];
29 | }
30 | }
31 |
32 | while (!q.isEmpty()) {
33 | const cur = q.dequeue();
34 | for (const node of graph[cur]) {
35 | result[node] = result[cur] + times[node];
36 |
37 | indegree[node]--;
38 | if (indegree[node] === 0) q.enqueue(node);
39 | }
40 | }
41 |
42 | for (let i = 1; i <= n; i++) {
43 | console.log(result[i]);
44 | }
45 | }
46 |
47 | solution(n, arr);
48 |
--------------------------------------------------------------------------------
/CHAPTER_10_그래프이론/팀 결성.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | function solution(n, m, arr) {
9 | const findParent = (parent, x) => {
10 | if (parent[x] === x) return parent[x];
11 | return (parent[x] = findParent(parent, parent[x]));
12 | };
13 |
14 | const unionParent = (parent, a, b) => {
15 | a = findParent(parent, a);
16 | b = findParent(parent, b);
17 | if (a < b) parent[b] = a;
18 | else parent[a] = b;
19 | };
20 |
21 | //parent 초기화
22 | let parent = [...Array(n + 1).fill(0)];
23 | for (let i = 0; i <= n; i++) {
24 | parent[i] = i;
25 | }
26 |
27 | let result = '';
28 | for (const value of arr) {
29 | const [type, u, v] = value;
30 | if (type === 0) {
31 | unionParent(parent, u, v);
32 | } else {
33 | result += parent[u] === parent[v] ? 'YES\n' : 'NO\n';
34 | }
35 | }
36 | return result;
37 | }
38 |
39 | console.log(solution(n, m, arr));
40 |
--------------------------------------------------------------------------------
/CHAPTER_11_그리디 문제/Q1_모험가 길드.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr] = input;
5 | n = +n;
6 | arr = arr.split(' ').map(Number);
7 |
8 | function solution(n, arr) {
9 | let group = 0;
10 |
11 | arr.sort((a, b) => a - b);
12 |
13 | let count = 0; //현재 그룹에 포함되는 모험가 수
14 | for (const fear of arr) {
15 | count++; //일단 현재 그룹에 포함
16 | if (count >= fear) {
17 | group++;
18 | count = 0;
19 | }
20 | }
21 |
22 | return group;
23 | }
24 |
25 | console.log(solution(n, arr));
26 |
--------------------------------------------------------------------------------
/CHAPTER_11_그리디 문제/Q2_곱하기 혹은 더하기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim();
3 |
4 | let s = input.split('').map(Number);
5 |
6 | function solution(s) {
7 | let result = 0;
8 | for (const num of s) {
9 | if (num <= 1 || result === 0) result += num;
10 | else result *= num;
11 | }
12 | return result;
13 | }
14 |
15 | console.log(solution(s));
16 |
--------------------------------------------------------------------------------
/CHAPTER_11_그리디 문제/Q3_문자열 뒤집기.js:
--------------------------------------------------------------------------------
1 | //0001100
2 |
3 | const fs = require('fs');
4 | let input = fs.readFileSync('../tc.txt').toString().trim();
5 |
6 | let s = input.split('').map(Number);
7 |
8 | function solution(s) {
9 | let group = [0, 0];
10 | group[s[0]]++;
11 |
12 | for (let i = 0; i < s.length - 1; i++) {
13 | if (s[i] !== s[i + 1]) {
14 | group[s[i + 1]]++;
15 | }
16 | }
17 |
18 | return Math.min(...group);
19 | }
20 |
21 | console.log(solution(s));
22 |
--------------------------------------------------------------------------------
/CHAPTER_11_그리디 문제/Q4_만들 수 없는 금액.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr] = input;
5 | n = +n;
6 | arr = arr.split(' ').map(Number);
7 |
8 | function solution(n, arr) {
9 | arr.sort((a, b) => a - b);
10 |
11 | let target = 1;
12 | for (const coin of arr) {
13 | if (target < coin) break;
14 | target += coin;
15 | }
16 |
17 | return target;
18 | }
19 |
20 | console.log(solution(n, arr));
21 |
--------------------------------------------------------------------------------
/CHAPTER_11_그리디 문제/Q5_볼링공 고르기.js:
--------------------------------------------------------------------------------
1 | // 5 3
2 | // 1 3 2 3 2
3 |
4 | const fs = require('fs');
5 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
6 |
7 | let [nm, arr] = input;
8 | const [n, m] = nm.split(' ').map(Number);
9 | arr = arr.split(' ').map(Number);
10 |
11 | function solution(n, m, arr) {
12 | const nC2 = (n) => {
13 | return (n * (n - 1)) / 2;
14 | };
15 |
16 | let weight = [...Array(11).fill(0)]; //무게별 볼링공 개수
17 | for (const w of arr) {
18 | weight[w]++;
19 | }
20 |
21 | let dup = 0;
22 | for (let i = 1; i <= m; i++) {
23 | if (weight[i] > 1) {
24 | dup += nC2(weight[i]); //같은 무게의 공을 선택하는 경우ㄴ
25 | }
26 | }
27 |
28 | return nC2(n) - dup;
29 | }
30 |
31 | console.log(solution(n, m, arr));
32 |
--------------------------------------------------------------------------------
/CHAPTER_12_구현 문제/Q10_자물쇠와 열쇠.js:
--------------------------------------------------------------------------------
1 | //시계 방향으로 90도 회전
2 | const rotateMatrix90 = (arr) => {
3 | const n = arr.length; //행 길이
4 | const m = arr[1].length; //열 길이
5 | const result = Array.from(Array(n), () => Array(m).fill(0));
6 | for (let i = 0; i < n; i++) {
7 | for (let j = 0; j < m; j++) {
8 | result[j][n - i - 1] = arr[i][j];
9 | }
10 | }
11 | return result;
12 | };
13 |
14 | const check = (arr) => {
15 | const n = arr.length / 3;
16 | for (let i = n; i < 2 * n; i++) {
17 | for (let j = n; j < 2 * n; j++) {
18 | if (arr[i][j] != 1) return false;
19 | }
20 | }
21 | return true;
22 | };
23 |
24 | function solution(key, lock) {
25 | const n = lock.length;
26 | const m = key.length;
27 |
28 | //n + 2*(m-1) < 3*n 이므로, 편의상 3배 확장
29 | const newLock = Array.from(Array(n * 3), () => Array(n * 3).fill(0));
30 | for (let i = 0; i < n; i++) {
31 | for (let j = 0; j < n; j++) {
32 | newLock[i + n][j + n] = lock[i][j];
33 | }
34 | }
35 |
36 | for (let k = 0; k < 4; k++) {
37 | key = rotateMatrix90(key);
38 | for (let x = 0; x < n * 2; x++) {
39 | for (let y = 0; y < n * 2; y++) {
40 | //자물쇠에 열쇠 넣기
41 | for (let i = 0; i < m; i++) {
42 | for (let j = 0; j < m; j++) {
43 | newLock[x + i][y + j] += key[i][j];
44 | }
45 | }
46 |
47 | if (check(newLock)) return true;
48 |
49 | //자물쇠에서 열쇠 빼기
50 | for (let i = 0; i < m; i++) {
51 | for (let j = 0; j < m; j++) {
52 | newLock[x + i][y + j] -= key[i][j];
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
59 | return false;
60 | }
61 |
--------------------------------------------------------------------------------
/CHAPTER_12_구현 문제/Q11_뱀.js:
--------------------------------------------------------------------------------
1 | //#1
2 | const readline = require('readline');
3 |
4 | const rl = readline.createInterface({
5 | input: process.stdin,
6 | output: process.stdout,
7 | });
8 |
9 | let input = [];
10 |
11 | rl.on('line', function (line) {
12 | input.push(line);
13 | }).on('close', function () {
14 | let [n, k, ...rest] = input;
15 | (n = +n), (k = +k);
16 |
17 | const apples = [];
18 | for (let i = 0; i < k; i++) apples.push(rest[i].split(' ').map((v) => +v));
19 |
20 | const l = +rest[apples.length];
21 | const dirs = rest
22 | .slice(apples.length + 1, rest.length)
23 | .map((str) => str.split(' '));
24 |
25 | function solution(n, k, apples, l, dirs) {
26 | let time = 0;
27 | let arr = Array.from(Array(n + 1), () => Array(n + 1).fill(0));
28 | for (const [x, y] of apples) {
29 | arr[x][y] = 1;
30 | }
31 |
32 | let changeDir = [...Array(10001).fill(0)];
33 | for (const [x, c] of dirs) {
34 | changeDir[+x] = c;
35 | }
36 |
37 | const dx = [0, 1, 0, -1];
38 | const dy = [1, 0, -1, 0];
39 | let cur = 0; //현재 방향
40 |
41 | let x = 1,
42 | y = 1;
43 | const q = []; //뱀의 위치 정보
44 | q.push([x, y]);
45 | arr[x][y] = 2;
46 |
47 | while (1) {
48 | if (changeDir[time] === 'D') {
49 | cur = (cur + 1) % 4;
50 | } else if (changeDir[time] === 'L') {
51 | cur = cur ? cur - 1 : 3;
52 | }
53 | const nx = x + dx[cur];
54 | const ny = y + dy[cur];
55 |
56 | time++;
57 |
58 | //벽에 부딪히는 경우
59 | if (nx < 1 || nx > n || ny < 1 || ny > n) {
60 | return time;
61 | }
62 | //자기 몸에 부딪히는 경우
63 | if (arr[nx][ny] === 2) {
64 | return time;
65 | }
66 |
67 | //사과가 없는 경우 꼬리 제거
68 | if (arr[nx][ny] === 0) {
69 | const [px, py] = q.shift();
70 | arr[px][py] = 0;
71 | }
72 | arr[nx][ny] = 2;
73 | q.push([nx, ny]);
74 | x = nx;
75 | y = ny;
76 | }
77 | }
78 |
79 | console.log(solution(n, k, apples, l, dirs));
80 |
81 | process.exit();
82 | });
83 |
84 | //#2
85 | function solution(n, k, apples, l, dirs) {
86 | let arr = Array.from(Array(n), () => Array(n).fill(0));
87 | for (const [x, y] of apples) {
88 | arr[x - 1][y - 1] = 1;
89 | }
90 |
91 | const d = [
92 | [0, 1],
93 | [1, 0],
94 | [0, -1],
95 | [-1, 0],
96 | ];
97 |
98 | let sec = 0; //시간
99 | let curD = 0; //현재 바라보는 방향
100 |
101 | arr[0][0] = 2; //뱀이 위치
102 | let head = [0, 0]; //뱀 머리 위치
103 |
104 | const snake = [];
105 | snake.push(head);
106 |
107 | while (1) {
108 | sec++;
109 |
110 | const [x, y] = head;
111 | const [dx, dy] = d[curD];
112 | const nx = x + dx;
113 | const ny = y + dy;
114 |
115 | if (nx < 0 || nx >= n || ny < 0 || ny >= n) return sec; //벽에 부딪히는 경우
116 | if (arr[nx][ny] === 2) return sec; //자기 몸과 부딪히는 경우
117 |
118 | //사과가 없는 경우 꼬리 이동
119 | if (arr[nx][ny] === 0) {
120 | const tail = snake.shift();
121 | arr[tail[0]][tail[1]] = 0;
122 | }
123 | arr[nx][ny] = 2;
124 | head = [nx, ny];
125 | snake.push([nx, ny]);
126 |
127 | for (const [X, C] of dirs) {
128 | if (Number(X) === sec) {
129 | if (C === 'D') curD = (curD + 1) % 4;
130 | else curD = curD === 0 ? 3 : curD - 1;
131 | }
132 | }
133 | }
134 | }
135 |
136 | console.log(solution(n, k, apples, l, dirs));
137 |
--------------------------------------------------------------------------------
/CHAPTER_12_구현 문제/Q13_치킨 배달.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map(Number);
6 | arr = arr.map((str) => str.split(' ').map(Number));
7 |
8 | function solution(n, m, arr) {
9 | const chickens = [];
10 | const houses = [];
11 | for (let i = 0; i < n; i++) {
12 | for (let j = 0; j < n; j++) {
13 | if (arr[i][j] === 1) {
14 | houses.push([i + 1, j + 1]);
15 | } else if (arr[i][j] === 2) {
16 | chickens.push([i + 1, j + 1]);
17 | }
18 | }
19 | }
20 |
21 | let ans = Infinity;
22 |
23 | const nCr = (cur, tmp) => {
24 | if (tmp.length === m) {
25 | let sum = 0;
26 | for (let i = 0; i < houses.length; i++) {
27 | const [r1, c1] = houses[i];
28 | let min = Infinity;
29 | for (let j = 0; j < m; j++) {
30 | const [r2, c2] = chickens[tmp[j]];
31 | min = Math.min(min, Math.abs(r1 - r2) + Math.abs(c1 - c2));
32 | }
33 | sum += min;
34 | }
35 | ans = Math.min(ans, sum);
36 | return;
37 | }
38 |
39 | for (let i = cur; i < chickens.length; i++) {
40 | tmp.push(i);
41 | nCr(i + 1, tmp);
42 | tmp.pop();
43 | }
44 | };
45 |
46 | nCr(0, []);
47 |
48 | return ans;
49 | }
50 |
51 | console.log(solution(n, m, arr));
52 |
--------------------------------------------------------------------------------
/CHAPTER_12_구현 문제/Q7_럭키 스트레이트.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim();
3 |
4 | let point = input.split('').map(Number);
5 |
6 | function solution(point) {
7 | const n = point.length;
8 | const left = point.slice(0, n / 2).reduce((a, b) => a + b);
9 | const right = point.slice(n / 2).reduce((a, b) => a + b);
10 | return left === right ? 'LUCKY' : 'READY';
11 | }
12 |
13 | console.log(solution(point));
14 |
--------------------------------------------------------------------------------
/CHAPTER_12_구현 문제/Q8_문자열 재정렬.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim();
3 |
4 | let str = input;
5 |
6 | function solution(str) {
7 | let result = [];
8 | let sum = 0;
9 | for (const s of str) {
10 | if (isNaN(s)) {
11 | result.push(s);
12 | } else {
13 | sum += +s;
14 | }
15 | }
16 |
17 | result.sort();
18 | if (sum) result.push(sum);
19 |
20 | return result.join('');
21 | }
22 |
23 | console.log(solution(str));
24 |
--------------------------------------------------------------------------------
/CHAPTER_12_구현 문제/Q9_문자열 압축.js:
--------------------------------------------------------------------------------
1 | //#1
2 | function solution(str) {
3 | const n = str.length;
4 | let ans = n;
5 |
6 | //i는 압축 단위
7 | for (let i = 1; i <= ~~(n / 2); i++) {
8 | const result = [];
9 | for (let j = 0; j < n; j += i) {
10 | const sub = str.slice(j, i + j);
11 | result.push(sub);
12 | }
13 |
14 | let compressed = '';
15 | let cnt = 1;
16 |
17 | for (let j = 0; j < result.length; j++) {
18 | if (result[j] === result[j + 1]) {
19 | cnt++;
20 | } else {
21 | compressed += `${cnt === 1 ? '' : cnt}${result[j]}`;
22 | cnt = 1;
23 | }
24 | }
25 |
26 | ans = Math.min(ans, compressed.length);
27 | }
28 |
29 | return ans;
30 | }
31 |
32 | //#2
33 | function solution(str) {
34 | const n = str.length;
35 | let min = n;
36 |
37 | for (let i = 1; i <= n; i++) {
38 | let prev = 0;
39 | let cnt = 1;
40 | let ans = '';
41 |
42 | while (prev <= n) {
43 | const cur = str.slice(prev, prev + i);
44 |
45 | if (cur === str.slice(prev + i, prev + i * 2)) {
46 | cnt++;
47 | } else {
48 | ans += `${cnt > 1 ? cnt : ''}${cur}`;
49 | cnt = 1;
50 | }
51 | prev += i;
52 | }
53 |
54 | min = Math.min(min, ans.length);
55 | }
56 |
57 | return min;
58 | }
59 |
--------------------------------------------------------------------------------
/CHAPTER_13_DFSBFS 문제/Q15_특정 거리의 도시 찾기.js:
--------------------------------------------------------------------------------
1 | class Node {
2 | constructor(data) {
3 | this.data = data;
4 | this.next = null;
5 | }
6 | }
7 |
8 | class Queue {
9 | constructor() {
10 | this.front = null;
11 | this.rear = null;
12 | this.size = 0;
13 | }
14 |
15 | isEmpty() {
16 | return this.size === 0;
17 | }
18 |
19 | enqueue(data) {
20 | const newNode = new Node(data);
21 | if (this.isEmpty()) this.front = newNode;
22 | else this.rear.next = newNode;
23 | this.rear = newNode;
24 | this.size++;
25 | }
26 |
27 | dequeue() {
28 | if (this.isEmpty()) return;
29 | const data = this.front.data;
30 | this.front = this.front.next;
31 | this.size--;
32 | return data;
33 | }
34 | }
35 |
36 | const readline = require('readline');
37 |
38 | const rl = readline.createInterface({
39 | input: process.stdin,
40 | output: process.stdout,
41 | });
42 |
43 | let input = [];
44 |
45 | rl.on('line', function (line) {
46 | input.push(line);
47 | }).on('close', function () {
48 | let [nmkx, ...arr] = input;
49 | const [n, m, k, x] = nmkx.split(' ').map((v) => +v);
50 | arr = arr.map((str) => str.split(' ').map((v) => +v));
51 |
52 | function solution(n, m, k, x, arr) {
53 | const graph = Array.from(Array(n + 1), () => []);
54 | for (const [u, v] of arr) {
55 | graph[u].push(v);
56 | }
57 |
58 | let dist = [...Array(n + 1).fill(-1)];
59 | dist[x] = 0;
60 |
61 | const q = new Queue();
62 | q.enqueue(x);
63 |
64 | while (!q.isEmpty()) {
65 | const cur = q.dequeue();
66 | for (const next of graph[cur]) {
67 | if (dist[next] === -1) {
68 | dist[next] = dist[cur] + 1;
69 | q.enqueue(next);
70 | }
71 | }
72 | }
73 |
74 | const result = [];
75 | for (const i in dist) {
76 | if (dist[i] === k) result.push(+i);
77 | }
78 | result.sort((a, b) => a - b);
79 |
80 | let print = '';
81 | for (const r of result) {
82 | print += `${r}\n`;
83 | }
84 |
85 | return result.length ? print : -1;
86 | }
87 |
88 | console.log(solution(n, m, k, x, arr));
89 |
90 | process.exit();
91 | });
92 |
--------------------------------------------------------------------------------
/CHAPTER_13_DFSBFS 문제/Q16_연구소.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('./tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map(Number);
6 | arr = arr.map((str) => str.split(' ').map(Number));
7 |
8 | function solution(n, m, arr) {
9 | let ans = 0;
10 | let virus = [];
11 | for (let i = 0; i < n; i++) {
12 | for (let j = 0; j < m; j++) {
13 | if (arr[i][j] === 2) virus.push([i, j]);
14 | }
15 | }
16 |
17 | const dx = [0, -1, 0, 1];
18 | const dy = [-1, 0, 1, 0];
19 |
20 | let visited = Array.from(Array(n), () => Array(m).fill(false));
21 |
22 | const dfs = (x, y, graph) => {
23 | for (let i = 0; i < 4; i++) {
24 | const nx = x + dx[i];
25 | const ny = y + dy[i];
26 |
27 | if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
28 |
29 | if (graph[nx][ny] === 0) {
30 | graph[nx][ny] = 2;
31 | dfs(nx, ny, graph);
32 | }
33 | }
34 | };
35 |
36 | const nCr = (x, y, tmp) => {
37 | if (tmp.length === 3) {
38 | //3개의 벽 세우기
39 | let graph = JSON.parse(JSON.stringify(arr));
40 |
41 | for (const [i, j] of tmp) {
42 | graph[i][j] = 1;
43 | }
44 |
45 | //바이러스 퍼뜨리기
46 | for (const [i, j] of virus) {
47 | dfs(i, j, graph);
48 | }
49 |
50 | //안전 영역 계산
51 | let cnt = 0;
52 | for (let i = 0; i < n; i++) {
53 | for (let j = 0; j < m; j++) {
54 | if (graph[i][j] === 0) cnt++;
55 | }
56 | }
57 | ans = Math.max(ans, cnt);
58 | return;
59 | }
60 |
61 | for (let i = x; i < n; i++) {
62 | for (let j = y; j < m; j++) {
63 | if (!visited[i][j] && arr[i][j] === 0) {
64 | tmp.push([i, j]);
65 | visited[i][j] = true;
66 |
67 | nCr(i, j + 1, tmp);
68 |
69 | tmp.pop();
70 | visited[i][j] = false;
71 | }
72 | }
73 | y = 0; //다음 행에 대해서는 첫 번째 열부터 시작
74 | }
75 | };
76 |
77 | nCr(0, 0, []);
78 |
79 | return ans;
80 | }
81 |
82 | console.log(solution(n, m, arr));
83 |
--------------------------------------------------------------------------------
/CHAPTER_13_DFSBFS 문제/Q17_경쟁적 전염.js:
--------------------------------------------------------------------------------
1 | class Node {
2 | constructor(data) {
3 | this.data = data;
4 | this.next = null;
5 | }
6 | }
7 |
8 | class Queue {
9 | constructor() {
10 | this.front = null;
11 | this.rear = null;
12 | this.size = 0;
13 | }
14 |
15 | isEmpty() {
16 | return this.size === 0;
17 | }
18 |
19 | enqueue(data) {
20 | const newNode = new Node(data);
21 | if (this.isEmpty()) this.front = newNode;
22 | else this.rear.next = newNode;
23 | this.rear = newNode;
24 | this.size++;
25 | }
26 |
27 | dequeue() {
28 | if (this.isEmpty()) return;
29 | const data = this.front.data;
30 | this.front = this.front.next;
31 | this.size--;
32 | return data;
33 | }
34 | }
35 |
36 | const fs = require('fs');
37 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
38 |
39 | let [nk, ...rest] = input;
40 | const [n, k] = nk.split(' ').map((v) => +v);
41 | const arr = rest.slice(0, n).map((str) => str.split(' ').map((v) => +v));
42 | const [s, x, y] = rest[n].split(' ').map((v) => +v);
43 |
44 | function solution(n, k, arr, s, x, y) {
45 | const virus = [];
46 | for (let i = 0; i < n; i++) {
47 | for (let j = 0; j < n; j++) {
48 | if (arr[i][j] !== 0) {
49 | virus.push([arr[i][j], 0, i, j]);
50 | }
51 | }
52 | }
53 | virus.sort((a, b) => a[0] - b[0]);
54 |
55 | const dx = [-1, 0, 1, 0];
56 | const dy = [0, 1, 0, -1];
57 |
58 | const q = new Queue();
59 | for (const v of virus) q.enqueue(v);
60 |
61 | while (!q.isEmpty()) {
62 | const [num, time, x, y] = q.dequeue();
63 |
64 | if (time === s) break;
65 |
66 | for (let i = 0; i < 4; i++) {
67 | const nx = x + dx[i];
68 | const ny = y + dy[i];
69 |
70 | if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
71 |
72 | if (arr[nx][ny] == 0) {
73 | arr[nx][ny] = num;
74 | q.enqueue([num, time + 1, nx, ny]);
75 | }
76 | }
77 | }
78 |
79 | return arr[x - 1][y - 1];
80 | }
81 |
82 | console.log(solution(n, k, arr, s, x, y));
83 |
--------------------------------------------------------------------------------
/CHAPTER_13_DFSBFS 문제/Q18_괄호 변환.js:
--------------------------------------------------------------------------------
1 | const check = (str) => {
2 | const s = [];
3 | for (let i = 0; i < str.length; i++) {
4 | if (str[i] === '(') {
5 | s.push('(');
6 | } else {
7 | if (s.length === 0) return false;
8 | s.pop();
9 | }
10 | }
11 | if (s.length !== 0) return false;
12 | return true;
13 | };
14 |
15 | function solution(p) {
16 | //step1
17 | if (p === '') return '';
18 |
19 | //step2
20 | let a = 0,
21 | b = 0;
22 | let u = '',
23 | v = '';
24 | for (let i = 0; i < p.length; i++) {
25 | if (p[i] === '(') a++;
26 | else b++;
27 |
28 | if (a === b) {
29 | u = p.slice(0, i + 1);
30 | v = p.slice(i + 1);
31 | break;
32 | }
33 | }
34 |
35 | if (check(u)) {
36 | //step3
37 | return u + solution(v);
38 | } else {
39 | //step4
40 | let tmp = '(';
41 | tmp += solution(v);
42 | tmp += ')';
43 |
44 | u = u.slice(1, u.length - 1);
45 | for (let i = 0; i < u.length; i++) {
46 | if (u[i] === '(') tmp += ')';
47 | else tmp += '(';
48 | }
49 | return tmp;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CHAPTER_13_DFSBFS 문제/Q19_연산자 끼워 넣기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr, op] = input;
5 | n = +n;
6 | arr = arr.split(' ').map(Number);
7 | op = op.split(' ').map(Number);
8 |
9 | function solution(n, arr, op) {
10 | let min = Infinity;
11 | let max = -Infinity;
12 |
13 | const dfs = (idx, add, sub, mul, div, result) => {
14 | if (idx === n) {
15 | min = Math.min(min, result);
16 | max = Math.max(max, result);
17 | return;
18 | }
19 |
20 | if (add > 0) dfs(idx + 1, add - 1, sub, mul, div, result + arr[idx]);
21 | if (sub > 0) dfs(idx + 1, add, sub - 1, mul, div, result - arr[idx]);
22 | if (mul > 0) dfs(idx + 1, add, sub, mul - 1, div, result * arr[idx]);
23 | if (div > 0) dfs(idx + 1, add, sub, mul, div - 1, ~~(result / arr[idx]));
24 | };
25 |
26 | dfs(1, op[0], op[1], op[2], op[3], arr[0]);
27 |
28 | return `${max}\n${min}`;
29 | }
30 |
31 | console.log(solution(n, arr, op));
32 |
--------------------------------------------------------------------------------
/CHAPTER_13_DFSBFS 문제/Q20_감시 피하기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, ...arr] = input;
5 | n = +n;
6 | arr = arr.map((str) => str.split(' '));
7 |
8 | function solution(n, arr) {
9 | const teachers = [];
10 | for (let i = 0; i < n; i++) {
11 | for (let j = 0; j < n; j++) {
12 | if (arr[i][j] === 'T') teachers.push([i, j]);
13 | }
14 | }
15 |
16 | const dx = [0, -1, 0, 1];
17 | const dy = [-1, 0, 1, 0];
18 | let visited = Array.from(Array(n), () => Array(n).fill(false));
19 |
20 | const avoid = (graph) => {
21 | for (const [x, y] of teachers) {
22 | //상
23 | for (let i = x; i >= 0; i--) {
24 | if (graph[i][y] === 'O') break;
25 | if (graph[i][y] === 'S') return false;
26 | }
27 |
28 | //하
29 | for (let i = x; i < n; i++) {
30 | if (graph[i][y] === 'O') break;
31 | if (graph[i][y] === 'S') return false;
32 | }
33 |
34 | //좌
35 | for (let i = y; i >= 0; i--) {
36 | if (graph[x][i] === 'O') break;
37 | if (graph[x][i] === 'S') return false;
38 | }
39 |
40 | //우
41 | for (let i = y; i < n; i++) {
42 | if (graph[x][i] === 'O') break;
43 | if (graph[x][i] === 'S') return false;
44 | }
45 | }
46 |
47 | return true;
48 | };
49 |
50 | let flag = false;
51 | const nCr = (x, y, tmp) => {
52 | if (flag) return; //감시를 피할 수 있는 경우가 하나라도 존재한다면 종료
53 |
54 | if (tmp.length === 3) {
55 | //장애물 3개 설치
56 | let graph = JSON.parse(JSON.stringify(arr));
57 | for (const [x, y] of tmp) {
58 | graph[x][y] = 'O';
59 | }
60 | //감시를 피할 수 있는지 체크
61 | flag ||= avoid(graph);
62 | return;
63 | }
64 |
65 | for (let i = x; i < n; i++) {
66 | for (let j = y; j < n; j++) {
67 | if (!visited[i][j] && arr[i][j] === 'X') {
68 | tmp.push([i, j]);
69 | visited[i][j] = true;
70 |
71 | nCr(i, j + 1, tmp);
72 |
73 | tmp.pop();
74 | visited[i][j] = false;
75 | }
76 | }
77 | y = 0;
78 | }
79 | };
80 |
81 | nCr(0, 0, []);
82 |
83 | return flag ? 'YES' : 'NO';
84 | }
85 |
86 | console.log(solution(n, arr));
87 |
--------------------------------------------------------------------------------
/CHAPTER_14_정렬 문제/Q23_국영수.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, ...arr] = input;
5 | n = +n;
6 | arr = arr.map((str) => str.split(' ').map((v) => (isNaN(v) ? v : +v)));
7 |
8 | function solution(n, arr) {
9 | arr.sort((a, b) => {
10 | const [name1, kor1, eng1, math1] = a;
11 | const [name2, kor2, eng2, math2] = b;
12 |
13 | if (kor1 === kor2) {
14 | if (eng1 === eng2) {
15 | if (math1 === math2) {
16 | if (name1 < name2) return -1;
17 | else return 1;
18 | }
19 | return math2 - math1;
20 | }
21 | return eng1 - eng2;
22 | }
23 | return kor2 - kor1;
24 | });
25 |
26 | return arr.map((v) => v[0]).join('\n');
27 | }
28 |
29 | console.log(solution(n, arr));
30 |
--------------------------------------------------------------------------------
/CHAPTER_14_정렬 문제/Q24_안테나.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr] = input;
5 | n = +n;
6 | arr = arr.split(' ').map((v) => +v);
7 |
8 | function solution(n, arr) {
9 | arr.sort((a, b) => a - b);
10 | const mid = ~~((n - 1) / 2); //합이 같은 경우(= n이 짝수) 작은 값을 원하므로 n-1 설정
11 | return arr[mid];
12 | }
13 |
14 | console.log(solution(n, arr));
15 |
--------------------------------------------------------------------------------
/CHAPTER_14_정렬 문제/Q25_실패율.js:
--------------------------------------------------------------------------------
1 | const n = 5;
2 | const stages = [2, 1, 2, 6, 2, 4, 3, 3];
3 |
4 | function solution(n, stages) {
5 | const stageCnt = [...Array(n + 2).fill(0)];
6 | for (const stage of stages) {
7 | stageCnt[stage]++;
8 | }
9 |
10 | let p = stages.length;
11 | const fail = [];
12 | for (let i = 1; i <= n; i++) {
13 | const x = stageCnt[i]; //i번 스테이지에 도달했으나 아직 클리어하지 못한 플레이어 수
14 | p -= stageCnt[i - 1]; //스테이지에 도달한 플레이어 수
15 | fail.push([x / p, i]); //[실패율, 스테이지]
16 | }
17 |
18 | fail.sort((a, b) => b[0] - a[0]);
19 |
20 | return fail.map((v) => v[1]);
21 | }
22 |
23 | console.log(solution(n, stages));
24 |
--------------------------------------------------------------------------------
/CHAPTER_14_정렬 문제/Q26_카드 정렬하기.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 먼저 더하는 카드 묶음이 n-1번씩 더 더해지므로, 먼저 더하는 값들이 작아야 한다.
3 | * 즉, 매 순간 가장 작은 값 두개씩 더해 나가면 된다.
4 | */
5 |
6 | //최소힙
7 | class PriorityQueue {
8 | constructor() {
9 | this.heap = [];
10 | }
11 |
12 | size() {
13 | return this.heap.length;
14 | }
15 |
16 | empty() {
17 | return this.size() === 0;
18 | }
19 |
20 | peek() {
21 | return this.heap[0];
22 | }
23 |
24 | push(data) {
25 | this.heap.push(data);
26 |
27 | let i = this.heap.length - 1;
28 | while (i > 0) {
29 | const parent = ~~((i - 1) / 2);
30 | if (this.heap[parent] <= this.heap[i]) break;
31 | [this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];
32 | i = parent;
33 | }
34 | }
35 |
36 | pop() {
37 | if (this.empty()) return;
38 |
39 | const value = this.peek();
40 | [this.heap[0], this.heap[this.heap.length - 1]] = [
41 | this.heap[this.heap.length - 1],
42 | this.heap[0],
43 | ];
44 | this.heap.pop();
45 | this._heapify();
46 | return value;
47 | }
48 |
49 | _heapify() {
50 | const x = this.peek();
51 | const n = this.heap.length;
52 | let cur = 0;
53 |
54 | while (2 * cur + 1 < n) {
55 | const leftChild = 2 * cur + 1;
56 | const rightChild = leftChild + 1;
57 | const smallerChild =
58 | rightChild < n && this.heap[rightChild] < this.heap[leftChild]
59 | ? rightChild
60 | : leftChild;
61 |
62 | //루트 노드의 값이 더 큰 경우 swap
63 | if (x > this.heap[smallerChild]) {
64 | [this.heap[cur], this.heap[smallerChild]] = [
65 | this.heap[smallerChild],
66 | this.heap[cur],
67 | ];
68 | cur = smallerChild;
69 | } else {
70 | break;
71 | }
72 | }
73 | }
74 | }
75 |
76 | const fs = require('fs');
77 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
78 |
79 | let [n, ...arr] = input;
80 | n = +n;
81 | arr = arr.map((v) => +v);
82 |
83 | function solution(n, arr) {
84 | arr.sort((a, b) => a - b);
85 |
86 | const pq = new PriorityQueue();
87 | for (const card of arr) {
88 | pq.push(card);
89 | }
90 |
91 | let sum = 0;
92 | let result = 0;
93 | while (pq.size() !== 1) {
94 | const first = pq.pop();
95 | const second = pq.pop();
96 | sum = first + second;
97 | result += sum;
98 | pq.push(sum);
99 | }
100 |
101 | return result;
102 | }
103 |
104 | console.log(solution(n, arr));
105 |
--------------------------------------------------------------------------------
/CHAPTER_15_이진탐색 문제/Q27_정렬된 배열에서 특정 수의 개수 구하기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nx, arr] = input;
5 | const [n, x] = nx.split(' ').map(Number);
6 | arr = arr.split(' ').map(Number);
7 |
8 | //#1
9 | function solution(n, x, arr) {
10 | let min = Infinity; //x가 등장하는 첫 번째 인덱스
11 | let max = -Infinity; //x가 등장하는 마지막 인덱스
12 | let flag = false;
13 |
14 | const binarySearch = (start, end, target) => {
15 | if (start > end) return;
16 |
17 | const mid = ~~((start + end) / 2);
18 |
19 | if (arr[mid] === target) {
20 | flag = true;
21 | min = Math.min(min, mid);
22 | max = Math.max(max, mid);
23 | }
24 |
25 | binarySearch(start, mid - 1, target);
26 | binarySearch(mid + 1, end, target);
27 | };
28 |
29 | binarySearch(0, n - 1, x);
30 |
31 | return flag ? max - min + 1 : -1;
32 | }
33 |
34 | //#2
35 | function solution2(n, m, arr) {
36 | const set = new Set();
37 | const binarySearch = (start, end, target) => {
38 | if (start > end) return -1;
39 |
40 | const mid = ~~((start + end) / 2);
41 | if (arr[mid] === target) set.add(mid);
42 | binarySearch(start, mid - 1, target);
43 | binarySearch(mid + 1, end, target);
44 | };
45 |
46 | binarySearch(0, n, m);
47 |
48 | return set.size || -1;
49 | }
50 |
51 | console.log(solution(n, x, arr));
52 |
--------------------------------------------------------------------------------
/CHAPTER_15_이진탐색 문제/Q28_고정점 찾기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr] = input;
5 | n = +n;
6 | arr = arr.split(' ').map((v) => +v);
7 |
8 | function solution(n, arr) {
9 | const binarySearch = (start, end) => {
10 | if (start > end) return;
11 |
12 | const mid = ~~((start + end) / 2);
13 | if (arr[mid] === mid) return mid;
14 | else if (arr[mid] > mid) return binarySearch(start, mid - 1);
15 | else return binarySearch(mid + 1, end);
16 | };
17 |
18 | return binarySearch(0, n - 1);
19 | }
20 |
21 | console.log(solution(n, arr));
22 |
--------------------------------------------------------------------------------
/CHAPTER_15_이진탐색 문제/Q29_공유기 설치.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nc, ...arr] = input;
5 | const [n, c] = nc.split(' ').map((v) => +v);
6 | arr = arr.map((v) => +v);
7 |
8 | function solution(n, c, arr) {
9 | arr.sort((a, b) => a - b);
10 | let ans = 0;
11 |
12 | //인접한 두 공유기 사이의 거리를 이진탐색으로 조절해 가며 조건(c개의 공유기 설치)을 만족하는지 탐색
13 | const binarySearch = (min, max) => {
14 | while (min <= max) {
15 | const mid = ~~((min + max) / 2);
16 |
17 | let cur = 0; //설치한 공유기 위치 (일단 첫 번째 집에 설치)
18 | let cnt = 1; //설치한 공유기 수
19 |
20 | for (let i = 1; i < n; i++) {
21 | //설치 가능한 경우
22 | if (arr[i] - arr[cur] >= mid) {
23 | cnt++;
24 | cur = i;
25 | }
26 | }
27 |
28 | //조건 확인
29 | if (cnt >= c) {
30 | min = mid + 1;
31 | ans = mid;
32 | } else {
33 | max = mid - 1;
34 | }
35 | }
36 | };
37 |
38 | binarySearch(0, arr[n - 1] - arr[0]);
39 |
40 | return ans;
41 | }
42 |
43 | console.log(solution(n, c, arr));
44 |
--------------------------------------------------------------------------------
/CHAPTER_16_다이나믹 프로그래밍 문제/Q31_금광.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [t, ...rest] = input;
5 | t = +t;
6 |
7 | let golds = [];
8 | let loop = t;
9 | while (loop--) {
10 | let [nm, arr, ...next] = rest;
11 | rest = next;
12 | const [n, m] = nm.split(' ').map((v) => +v);
13 | arr = arr.split(' ').map((v) => +v);
14 |
15 | const gold = [];
16 | for (let i = 0; i < n; i++) {
17 | const tmp = [];
18 | for (let j = 0; j < m; j++) {
19 | const idx = i * m + j;
20 | tmp.push(arr[idx]);
21 | }
22 | gold.push(tmp);
23 | }
24 | golds.push(gold);
25 | }
26 |
27 | function solution(t, golds) {
28 | let ans = '';
29 | for (const gold of golds) {
30 | const n = gold.length;
31 | const m = gold[0].length;
32 |
33 | let d = Array.from(Array(n), () => Array(m).fill(0));
34 | for (let i = 0; i < n; i++) {
35 | d[i][0] = gold[i][0];
36 | }
37 |
38 | for (let j = 1; j < m; j++) {
39 | for (let i = 0; i < n; i++) {
40 | if (i === 0)
41 | d[i][j] = Math.max(d[i][j - 1], d[i + 1][j - 1]) + gold[i][j];
42 | else if (i === n - 1)
43 | d[i][j] = Math.max(d[i - 1][j - 1], d[i][j - 1]) + gold[i][j];
44 | else
45 | d[i][j] =
46 | Math.max(d[i - 1][j - 1], d[i][j - 1], d[i + 1][j - 1]) +
47 | gold[i][j];
48 | }
49 | }
50 |
51 | let max = 0;
52 | for (let i = 0; i < n; i++) {
53 | max = Math.max(max, d[i][m - 1]);
54 | }
55 | ans += `${max}\n`;
56 | }
57 |
58 | return ans;
59 | }
60 |
61 | console.log(solution(t, golds));
62 |
--------------------------------------------------------------------------------
/CHAPTER_16_다이나믹 프로그래밍 문제/Q32_정수 삼각형.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, ...arr] = input;
5 | n = +n;
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | function solution(n, arr) {
9 | let d = Array.from(Array(n), () => Array(n).fill(0));
10 |
11 | d[0][0] = arr[0][0];
12 |
13 | for (let i = 1; i < n; i++) {
14 | for (let j = 0; j < arr[i].length; j++) {
15 | if (j === 0) d[i][j] = d[i - 1][j] + arr[i][j];
16 | else if (i === j) d[i][j] = d[i - 1][j - 1] + arr[i][j];
17 | else d[i][j] = Math.max(d[i - 1][j - 1], d[i - 1][j]) + arr[i][j];
18 | }
19 | }
20 |
21 | let max = 0;
22 | for (let j = 0; j < n; j++) {
23 | max = Math.max(max, d[n - 1][j]);
24 | }
25 |
26 | return max;
27 | }
28 |
29 | console.log(solution(n, arr));
30 |
--------------------------------------------------------------------------------
/CHAPTER_16_다이나믹 프로그래밍 문제/Q34_병사 배치하기.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, arr] = input;
5 | n = +n;
6 | arr = arr.split(' ').map((v) => +v);
7 |
8 | function solution(n, arr) {
9 | let d = [...Array(n).fill(1)];
10 |
11 | for (let i = 1; i < n; i++) {
12 | for (let j = i - 1; j >= 0; j--) {
13 | if (arr[j] > arr[i]) {
14 | d[i] = Math.max(d[i], d[j] + 1);
15 | }
16 | }
17 | }
18 |
19 | return n - Math.max(...d);
20 | }
21 |
22 | console.log(solution(n, arr));
23 |
--------------------------------------------------------------------------------
/CHAPTER_16_다이나믹 프로그래밍 문제/Q35_못생긴 수.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim();
3 |
4 | let n = +input;
5 |
6 | const MAX = 60000000;
7 | function solution(n) {
8 | let d = [...Array(MAX + 1).fill(false)];
9 | d[1] = true; //첫번째 못생긴 수 1
10 |
11 | const s = new Set();
12 | s.add(1);
13 |
14 | for (let i = 1; i <= MAX / 5; i++) {
15 | if (d[i]) {
16 | d[i * 2] = true;
17 | d[i * 3] = true;
18 | d[i * 5] = true;
19 |
20 | s.add(i * 2);
21 | s.add(i * 3);
22 | s.add(i * 5);
23 | }
24 | }
25 |
26 | return [...s].sort((a, b) => a - b)[n - 1];
27 | }
28 |
29 | console.log(solution(n));
30 |
--------------------------------------------------------------------------------
/CHAPTER_17_최단경로 문제/Q37_플로이드.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, m, ...arr] = input;
5 | (n = +n), (m = +m);
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | function solution(n, m, arr) {
9 | let d = Array.from(Array(n + 1), () => Array(n + 1).fill(Infinity));
10 | for (let i = 1; i <= n; i++) d[i][i] = 0;
11 | for (const [a, b, c] of arr) d[a][b] = Math.min(d[a][b], c); //노선이 여러개이므로 작은 값으로 초기화
12 |
13 | for (let k = 1; k <= n; k++) {
14 | for (let from = 1; from <= n; from++) {
15 | for (let to = 1; to <= n; to++) {
16 | d[from][to] = Math.min(d[from][to], d[from][k] + d[k][to]);
17 | }
18 | }
19 | }
20 |
21 | let ans = '';
22 | for (let i = 1; i <= n; i++) {
23 | for (let j = 1; j <= n; j++) {
24 | ans += `${d[i][j] === Infinity ? 0 : d[i][j]} `;
25 | }
26 | ans += '\n';
27 | }
28 | return ans;
29 | }
30 |
31 | console.log(solution(n, m, arr));
32 |
--------------------------------------------------------------------------------
/CHAPTER_17_최단경로 문제/Q38_정확한 순위.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | function solution(n, m, arr) {
9 | let d = Array.from(Array(n + 1), () => Array(n + 1).fill(false));
10 | for (let i = 1; i <= n; i++) d[i][i] = true;
11 | for (const [a, b] of arr) d[a][b] = true;
12 |
13 | for (let k = 1; k <= n; k++) {
14 | for (let from = 1; from <= n; from++) {
15 | for (let to = 1; to <= n; to++) {
16 | if (d[from][k] && d[k][to]) d[from][to] = true;
17 | }
18 | }
19 | }
20 |
21 | let ans = 0;
22 | for (let i = 1; i <= n; i++) {
23 | let count = 0;
24 | for (let j = 1; j <= n; j++) {
25 | if (d[i][j] || d[j][i]) {
26 | count++;
27 | }
28 | }
29 | if (count === n) {
30 | //모든 노드와 연결되어 있는 경우
31 | ans++;
32 | }
33 | }
34 |
35 | return ans;
36 | }
37 |
38 | console.log(solution(n, m, arr));
39 |
--------------------------------------------------------------------------------
/CHAPTER_17_최단경로 문제/Q39_화성 탐사.js:
--------------------------------------------------------------------------------
1 | //최소힙
2 | class PriorityQueue {
3 | constructor() {
4 | this.heap = [];
5 | }
6 |
7 | empty() {
8 | return this.heap.length === 0;
9 | }
10 |
11 | peek() {
12 | return this.heap[0];
13 | }
14 |
15 | push(data) {
16 | this.heap.push(data);
17 |
18 | let i = this.heap.length - 1;
19 | while (i > 0) {
20 | const parent = ~~((i - 1) / 2);
21 | if (this.heap[parent] <= this.heap[i]) break;
22 | [this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];
23 | i = parent;
24 | }
25 | }
26 |
27 | pop() {
28 | if (this.empty()) return;
29 |
30 | const value = this.peek();
31 | [this.heap[0], this.heap[this.heap.length - 1]] = [
32 | this.heap[this.heap.length - 1],
33 | this.heap[0],
34 | ];
35 | this.heap.pop();
36 | this._heapify();
37 | return value;
38 | }
39 |
40 | _heapify() {
41 | const x = this.peek();
42 | const n = this.heap.length;
43 | let cur = 0;
44 |
45 | while (2 * cur + 1 < n) {
46 | const leftChild = 2 * cur + 1;
47 | const rightChild = leftChild + 1;
48 | const smallerChild =
49 | rightChild < n && this.heap[rightChild] < this.heap[leftChild]
50 | ? rightChild
51 | : leftChild;
52 |
53 | //루트 노드의 값이 더 큰 경우 swap
54 | if (x > this.heap[smallerChild]) {
55 | [this.heap[cur], this.heap[smallerChild]] = [
56 | this.heap[smallerChild],
57 | this.heap[cur],
58 | ];
59 | cur = smallerChild;
60 | } else {
61 | break;
62 | }
63 | }
64 | }
65 | }
66 |
67 | const fs = require('fs');
68 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
69 |
70 | let [t, ...rest] = input;
71 | t = +t;
72 |
73 | let loop = t;
74 | const arr = [];
75 | while (loop--) {
76 | let [n, ...next] = rest;
77 | n = +n;
78 | rest = next.slice(n);
79 | arr.push(next.slice(0, n).map((str) => str.split(' ').map((v) => +v)));
80 | }
81 |
82 | function solution(t, arr) {
83 | let ans = '';
84 | for (let i = 0; i < t; i++) {
85 | const map = arr[i];
86 | const n = map.length;
87 | let d = Array.from(Array(n), () => Array(n).fill(Infinity));
88 |
89 | const dx = [-1, 0, 1, 0];
90 | const dy = [0, 1, 0, -1];
91 |
92 | const pq = new PriorityQueue();
93 | let sx = 0;
94 | let sy = 0;
95 | pq.push([map[sx][sy], sx, sy]);
96 | d[sx][sy] = map[sx][sy];
97 |
98 | while (!pq.empty()) {
99 | const [cost, x, y] = pq.pop();
100 |
101 | if (d[x][y] < cost) continue;
102 |
103 | for (let i = 0; i < 4; i++) {
104 | const nx = x + dx[i];
105 | const ny = y + dy[i];
106 |
107 | if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
108 |
109 | const nCost = cost + map[nx][ny];
110 | if (nCost < d[nx][ny]) {
111 | d[nx][ny] = nCost;
112 | pq.push([nCost, nx, ny]);
113 | }
114 | }
115 | }
116 |
117 | ans += `${d[n - 1][n - 1]}\n`;
118 | }
119 |
120 | return ans;
121 | }
122 |
123 | console.log(solution(t, arr));
124 |
--------------------------------------------------------------------------------
/CHAPTER_17_최단경로 문제/Q40_숨바꼭질.js:
--------------------------------------------------------------------------------
1 | class Node {
2 | constructor(data) {
3 | this.data = data;
4 | this.next = null;
5 | }
6 | }
7 |
8 | class Queue {
9 | constructor() {
10 | this.front = null;
11 | this.rear = null;
12 | this.size = 0;
13 | }
14 |
15 | empty() {
16 | return this.size === 0;
17 | }
18 |
19 | push(data) {
20 | const newNode = new Node(data);
21 | if (this.empty()) this.front = newNode;
22 | else this.rear.next = newNode;
23 | this.rear = newNode;
24 | this.size++;
25 | }
26 |
27 | pop() {
28 | if (this.empty()) return;
29 | const data = this.front.data;
30 | this.front = this.front.next;
31 | this.size--;
32 | return data;
33 | }
34 | }
35 |
36 | const fs = require('fs');
37 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
38 |
39 | let [nm, ...arr] = input;
40 | const [n, m] = nm.split(' ').map((v) => +v);
41 | arr = arr.map((str) => str.split(' ').map((v) => +v));
42 |
43 | function solution(n, m, arr) {
44 | let graph = Array.from(Array(n + 1), () => []);
45 | for (const [u, v] of arr) {
46 | graph[u].push(v);
47 | graph[v].push(u);
48 | }
49 |
50 | let d = [...Array(n + 1).fill(Infinity)];
51 |
52 | const q = new Queue();
53 | q.push(1);
54 | d[1] = 0;
55 |
56 | while (!q.empty()) {
57 | const cur = q.pop();
58 |
59 | for (const node of graph[cur]) {
60 | if (d[node] > d[cur] + 1) {
61 | d[node] = d[cur] + 1;
62 | q.push(node);
63 | }
64 | }
65 | }
66 |
67 | let max = 0;
68 | let maxIdx = 0;
69 | for (let i = 1; i <= n; i++) {
70 | if (max < d[i]) {
71 | max = d[i];
72 | maxIdx = i;
73 | }
74 | }
75 |
76 | const cnt = d.filter((v) => v === max).length;
77 |
78 | return [maxIdx, max, cnt].join(' ');
79 | }
80 |
81 | console.log(solution(n, m, arr));
82 |
--------------------------------------------------------------------------------
/CHAPTER_18_그래프 이론 문제/Q41_여행 계획.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...rest] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | const arr = rest.slice(0, n).map((str) => str.split(' ').map((v) => +v));
7 | const routes = rest[n].split(' ').map((v) => +v);
8 |
9 | function solution(n, m, arr, routes) {
10 | const findParent = (parent, x) => {
11 | if (parent[x] === x) return parent[x];
12 | return (parent[x] = findParent(parent, parent[x]));
13 | };
14 |
15 | const unionParent = (parent, a, b) => {
16 | a = findParent(parent, a);
17 | b = findParent(parent, b);
18 | if (a < b) {
19 | parent[b] = a;
20 | } else {
21 | parent[a] = b;
22 | }
23 | };
24 |
25 | const parent = [...Array(n + 1).fill(0)];
26 | for (let i = 1; i <= n; i++) parent[i] = i;
27 |
28 | for (let i = 0; i < n; i++) {
29 | for (let j = 0; j < n; j++) {
30 | if (i < j) continue;
31 | if (arr[i][j]) {
32 | unionParent(parent, i + 1, j + 1);
33 | }
34 | }
35 | }
36 |
37 | let flag = true;
38 | for (let i = 0; i < m - 1; i++) {
39 | if (findParent(parent, routes[i]) !== findParent(parent, routes[i + 1])) {
40 | flag = false;
41 | break;
42 | }
43 | }
44 | return flag ? 'YES' : 'NO';
45 | }
46 |
47 | console.log(solution(n, m, arr, routes));
48 |
--------------------------------------------------------------------------------
/CHAPTER_18_그래프 이론 문제/Q43_어두운 길.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [nm, ...arr] = input;
5 | const [n, m] = nm.split(' ').map((v) => +v);
6 | arr = arr.map((str) => str.split(' ').map((v) => +v));
7 |
8 | const findParent = (parent, x) => {
9 | if (parent[x] === x) return parent[x];
10 | return (parent[x] = findParent(parent, parent[x]));
11 | };
12 |
13 | const unionParent = (parent, a, b) => {
14 | a = findParent(parent, a);
15 | b = findParent(parent, b);
16 | if (a < b) parent[b] = a;
17 | else parent[a] = b;
18 | };
19 |
20 | function solution(n, m, arr) {
21 | let sum = 0;
22 | let graph = [];
23 | for (const [x, y, dist] of arr) {
24 | graph.push([dist, x, y]);
25 | sum += dist;
26 | }
27 | graph.sort((a, b) => a[0] - b[0]);
28 |
29 | let parent = [...Array(n).fill(0)];
30 | for (let i = 0; i < n; i++) parent[i] = i;
31 |
32 | let cost = 0;
33 | for (const [dist, x, y] of graph) {
34 | if (findParent(parent, x) !== findParent(parent, y)) {
35 | unionParent(parent, x, y);
36 | cost += dist;
37 | }
38 | }
39 |
40 | return sum - cost;
41 | }
42 |
43 | console.log(solution(n, m, arr));
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Javascript로 정리하는 [이것이 코딩 테스트다]
2 | 아래 도서를 Javascript 코드로 정리한 레포지토리입니다.
3 |
4 | 
5 |
6 |
7 |
8 | ## 문제 풀이 템플릿
9 | - 다른 언어와 달리, javascript는 입력을 받는 부분이 특이해 템플릿을 만들어 사용했습니다.
10 | - 입력을 받고 정제하는 부분과 문제 풀이 부분을 분리했습니다. (프로그래머스 방식 차용)
11 |
12 | cf) 백준 제출 시 입력 파일을 불러오는 부분을 `'/dev/stdin'`로 변경해야 합니다.
13 | ```javascript
14 | const fs = require('fs');
15 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
16 |
17 | let [n, ...arr] = input;
18 |
19 | function solution(n, arr) {
20 | let ans = 0;
21 | return ans;
22 | }
23 |
24 | console.log(solution(n, arr));
25 | ```
26 |
27 |
28 |
29 | ## 개념 정리 링크
30 | - https://gyyeom.tistory.com/category/Algorithm/Javascript%EB%A1%9C%20%EC%A0%95%EB%A6%AC%ED%95%98%EB%8A%94%20%EC%9D%B4%EC%BD%94%ED%85%8C
31 |
--------------------------------------------------------------------------------
/solution.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let input = fs.readFileSync('../tc.txt').toString().trim().split('\n');
3 |
4 | let [n, ...arr] = input;
5 |
6 | function solution(n, arr) {
7 | let ans = 0;
8 | return ans;
9 | }
10 |
11 | console.log(solution(n, arr));
12 |
--------------------------------------------------------------------------------
/tc.txt:
--------------------------------------------------------------------------------
1 | testcase
--------------------------------------------------------------------------------