diff --git a/find-minimum-in-rotated-sorted-array/jangwonyoon.js b/find-minimum-in-rotated-sorted-array/jangwonyoon.js new file mode 100644 index 0000000000..00a2275016 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/jangwonyoon.js @@ -0,0 +1,90 @@ +/** + * 153. Find Minimum in Rotated Sorted Array + * https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ + * + */ + +/** + * 풀이 1 + * 정렬 Sorting + * + * @param {number[]} nums + * @return {number} + * + * 시간 복잡도(TC): O(n log n) + * 공간 복잡도(SC): O(1) + * + * 관련 알고리즘: 정렬 Sorting + * + * 문제 풀이 방법: + * 1. 배열을 정렬하고 첫 번째 요소를 반환 + * + * 문제의 의도와 맞지 않는듯 + */ + +var findMin = function(nums) { + return nums.sort((a, b) => a - b)[0]; +}; + +/** + * 풀이 2 + * 투 포인터 Two Pointers + * + * @param {number[]} nums + * @return {number} + * + * 시간 복잡도(TC): O(n) + * 공간 복잡도(SC): O(1) + * + * 관련 알고리즘: 투 포인터 Two Pointers + * + * 문제 풀이 방법: + * 1. 배열을 순회하면서 최소값을 찾으면 된다. + * 2. 최소값을 찾으면 반환 + */ + +var findMin = function(nums) { + let result = Infinity; + + for (let i = 0; i < nums.length; i++) { + const curr = nums[i]; + result = Math.min(result, curr); + } + + return result; +}; + +/** + * 풀이 3 + * 이진 탐색 Binary Search + * + * @param {number[]} nums + * @return {number} + * + * 시간 복잡도(TC): O(log n) + * 공간 복잡도(SC): O(1) + * + * 관련 알고리즘: 이진 탐색 Binary Search + * + * 문제 풀이 방법: + * 1. 배열을 이진 탐색으로 탐색 + */ + +var findMin = function(nums) { + let left = 0; + let right = nums.length - 1; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + + // mid가 right보다 크면 최소값은 오른쪽 + if (nums[mid] > nums[right]) { + left = mid + 1; + } else { + // mid가 right보다 작다면 + right = mid; + } + } + + return nums[left]; +}; diff --git a/maximum-depth-of-binary-tree/jangwonyoon.js b/maximum-depth-of-binary-tree/jangwonyoon.js new file mode 100644 index 0000000000..88d78505bd --- /dev/null +++ b/maximum-depth-of-binary-tree/jangwonyoon.js @@ -0,0 +1,46 @@ +/** + * 104. Maximum Depth of Binary Tree + * https://leetcode.com/problems/maximum-depth-of-binary-tree/ + * + */ + +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ + +/* + * 시간 복잡도(TC): O(n) + * 공간 복잡도(SC): O(n) + * + * 관련 알고리즘: 분할 정복 Divide and Conquer, 재귀 Recursion + * + * 문제 풀이 방법: + * 1. 루트 노드가 없으면 0을 반환 + * 2. 루트 노드의 왼쪽 서브트리의 최대 깊이를 계산 + * 3. 루트 노드의 오른쪽 서브트리의 최대 깊이를 계산 + * 4. 루트 노드의 왼쪽 서브트리의 최대 깊이와 오른쪽 서브트리의 최대 깊이 중 더 큰 값을 반환 + * 5. 루트 노드의 왼쪽 서브트리의 최대 깊이와 오른쪽 서브트리의 최대 깊이 중 더 큰 값에 1을 더하여 반환 + */ + +var maxDepth = function(root) { + // 루트 노드가 없으면 0을 반환 + if (!root) return 0; + + // 루트 노드의 왼쪽 서브트리의 최대 깊이를 계산 + let left = maxDepth(root.left); + // 루트 노드의 오른쪽 서브트리의 최대 깊이를 계산 + let right = maxDepth(root.right); + + // 루트 노드의 왼쪽 서브트리의 최대 깊이와 오른쪽 서브트리의 최대 깊이 중 더 큰 값을 반환 + // 루트 노드의 왼쪽 서브트리의 최대 깊이와 오른쪽 서브트리의 최대 깊이 중 더 큰 값에 1을 더하여 반환 + return Math.max(left, right) + 1; +}; diff --git a/merge-two-sorted-lists/jangwonyoon.js b/merge-two-sorted-lists/jangwonyoon.js new file mode 100644 index 0000000000..fcb281707e --- /dev/null +++ b/merge-two-sorted-lists/jangwonyoon.js @@ -0,0 +1,41 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} list1 + * @param {ListNode} list2 + * @return {ListNode} + */ + +/* +* 시간 복잡도(TC): O(n + m) +- n: list1의 길이, m: list2의 길이 + +* 공간 복잡도(SC): O(n + m) +- 재귀 호출 시 스택 메모리가 최대 n+m 깊이까지 쌓일 수 있음 +*/ + +var mergeTwoLists = function(list1, list2) { + // 예외처리 - 둘 중 하나라도 리스트가 비어있으면, 그냥 다른 리스트를 반환. + if (!list1) return list2; + if (!list2) return list1; + + // 현재 노드 값 비교 + if (list1.val <= list2.val) { + // list1의 값이 더 작거나 같으면 + // list1의 결과 리스트의 head로 선택 + // list1.next는 남은 list1.next와 list2를 병합한 결과로 연결 + list1.next = mergeTwoLists(list1.next, list2); + return list1; + } else { + // list2의 값이 더 작으면 + // list2의 결과를 리스트의 head로 선택 + // list2.next는 list1과 list2.next를 병합한 결과로 연결 + list2.next = mergeTwoLists(list1, list2.next); + return list2; + } +}; diff --git a/word-search/jangwonyoon.js b/word-search/jangwonyoon.js new file mode 100644 index 0000000000..04974e2c93 --- /dev/null +++ b/word-search/jangwonyoon.js @@ -0,0 +1,123 @@ +/** + * 79. Word Search + * https://leetcode.com/problems/word-search/ + * + */ + +/* + * 시간 복잡도(TC): O(m * n * 4^L) + * m = 행, n = 열, L = 단어 길이 + * + * 공간 복잡도(SC): O(L) + * L = 단어 길이 + * + * 관련 알고리즘: 깊이 우선 탐색 Depth-First Search (DFS) + * + * 문제 풀이 방법: + * 1. 깊이 우선 탐색 (DFS)을 사용하여 시작점부터 첫 글자가 맞는 칸에서만 탐색 + * 2. 탐색 결과를 반환 + */ +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var exist = function(board, word) { + const rows = board.length; + const cols = board[0].length; + + function dfs(r, c, idx) { + // 1) 기저: 단어를 모두 매칭했을 경우 - 탈출 조건 + if (idx === word.length) return true; + + // 2) 가드: 범위/문자/방문 상태 확인 + if (r < 0 || r >= rows || c < 0 || c >= cols) return false; + if (board[r][c] !== word[idx]) return false; + if (board[r][c] === '#') return false; // 이미 방문했으면 탈락 + + // 3) 방문 마킹 + const tmp = board[r][c]; + board[r][c] = '#'; + + // 4방향 탐색 (상, 하, 좌, 우) + const ok = ㅋ + dfs(r + 1, c, idx + 1) || + dfs(r - 1, c, idx + 1) || + dfs(r, c + 1, idx + 1) || + dfs(r, c - 1, idx + 1); + + // 5) 복구 + board[r][c] = tmp; + + return ok; + } + + // 시작점: 첫 글자와 일치하는 칸에서만 DFS 시작 + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + // 첫 글자가 맞으면서 dfs가 성공했을 경우 true 반환 + if (board[row][col] === word[0] && dfs(row, col, 0)) return true; + } + } + + return false; +}; + +/** + * 풀이 2 + * 방문 배열 사용 + * + * 시간 복잡도(TC): O(m * n * 4^L) + * 공간 복잡도(SC): O(m * n) + * + * 관련 알고리즘: 깊이 우선 탐색 Depth-First Search (DFS) + * + * 문제 풀이 방법: + * 1. 방문 배열을 사용하여 방문한 칸을 체크 + + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ + +var exist = function(board, word) { + const rows = board.length; + const cols = board[0].length; + + // visited 배열 초기화 + const visited = Array.from({ length: rows }, () => Array(cols).fill(false)); + + function dfs(r, c, idx) { + // 1) 기저 조건: 단어를 모두 찾은 경우 + if (idx === word.length) return true; + + // 2) 가드 조건 + if (r < 0 || r >= rows || c < 0 || c >= cols) return false; + if (visited[r][c]) return false; + if (board[r][c] !== word[idx]) return false; + + // 3) 방문 처리 + visited[r][c] = true; + + // 4) 네 방향 탐색 + const ok = + dfs(r + 1, c, idx + 1) || + dfs(r - 1, c, idx + 1) || + dfs(r, c + 1, idx + 1) || + dfs(r, c - 1, idx + 1); + + // 5) 복구 (다른 경로에서 다시 쓸 수 있게) + visited[r][c] = false; + + return ok; + } + + // 6) 시작점 순회 + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + if (board[r][c] === word[0] && dfs(r, c, 0)) return true; + } + } + + return false; +};