├── 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 | ![book](https://user-images.githubusercontent.com/42757774/231062095-c9fea84c-722e-4ccb-941c-2a8e9cd8cb20.jpeg) 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 --------------------------------------------------------------------------------