From c47adc0cf2ec779e5e8fcd117df7a755f7314a9c Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Tue, 22 Jul 2025 11:57:20 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20coin-change=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coin-change/grapefruitgreentealoe.js | 74 ++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 coin-change/grapefruitgreentealoe.js diff --git a/coin-change/grapefruitgreentealoe.js b/coin-change/grapefruitgreentealoe.js new file mode 100644 index 0000000000..817f6c91f4 --- /dev/null +++ b/coin-change/grapefruitgreentealoe.js @@ -0,0 +1,74 @@ + +//1. top-down +var coinChange = function(coins, amount) { + if(amount == 0 ) return 0 + /* + 점화식 : dp[n] = Math.min(dp[n],dp[n-k]+1) + */ + const dp = new Array(amount+1).fill(Math.pow(10,4)); + for(let c of coins){ + dp[c] = 1 + } + function dfs(idx,coin){ + if(idx + coin > amount) return + dp[idx+coin] = Math.min(dp[idx+coin],dp[idx]+1) + if(idx + coin == amount){ + return + }else{ + for(let c of coins){ + //여기서 dfs를 안들어가는 방법은 없을까? + dfs(idx+coin,c) + } + } + } + dfs(0,coins[0]) + + if(dp[amount] > amount) return -1 + + return dp[amount] + +}; + +// 타임리밋에 걸린다. dfs의 가지치기가 덜 되어서 그렇다. +// 그렇다면, 순차적인 dp를 좀더 활용하는 것이 좋아보인다. 현재로서는 메모이제이션의 이점을 제대로 활용할 수 없어보인다. + + + +//2. bottom-up +var coinChange = function(coins, amount) { + coins = coins.filter(x=> x<=amount) + if(amount == 0) return 0 + /* + 점화식 : dp[n] = Math.min(dp[n],dp[n-k]+1) + */ + const dp = new Array(amount+1).fill(Math.pow(10,4)+1); + dp[0] = 0 + //dfs를 쓰고 싶지 않다면, amount만큼의 for문을 돌면서 dp를 초기화해주면 된다. + for(let i=1; i = 0){ + dp[i] = Math.min(dp[i-coin] + 1,dp[i]) + } + } + } + if(dp[amount] > amount) return -1 + return dp[amount] + +}; + +/** +dfs를 쓰고 싶지 않다면, amount만큼의 for문을 돌면서 dp를 초기화해주면 된다. +처음에 coins = coins.filter(x=> x<=amount) +이렇게 쓴 이유는, amount보다 작은 코인만 필터하여 최적화한다. + +이 문제 풀이 소요시간이 1시간이 넘었는데, +그 이유가, i-coin이 아니라, i+coin을 기준을 삼았었다. +그러다보니 그러다 보니 각 금액 `i`의 최솟값을 찾기 위해 `dp[i]`를 `dp[i-coin]` 기반으로 갱신해야 한다는 핵심적인 아이디어를 적용하기 어려웠다. +`dp[i+coin]` 방식으로 접근하면, `dp[i]` 자체가 아직 최적의 상태가 아닌데도 그 값을 기반으로 미래의 `dp[i+coin]`을 업데이트하려 하기 때문에, 정확한 최적해를 찾아내기 어려웠다. +현재 금액 `i`를 만들기 위한 가장 효율적인 방법을 과거의 `dp[i-coin]`에서 찾는 '바텀업(Bottom-Up)' 방식이 이 문제에 훨씬 적합하다는 것을 깨닫는 데 시간이 걸렸다. + + + +시간복잡도: O(n * m) +공간 복잡도 : O(n) + */ \ No newline at end of file From 21dedca6af3d3e34c079f017407bdbf55a981ba3 Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Sat, 26 Jul 2025 17:20:19 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20word-search=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- word-search/grapefruitgreentealoe.js | 62 ++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 word-search/grapefruitgreentealoe.js diff --git a/word-search/grapefruitgreentealoe.js b/word-search/grapefruitgreentealoe.js new file mode 100644 index 0000000000..3f2286929f --- /dev/null +++ b/word-search/grapefruitgreentealoe.js @@ -0,0 +1,62 @@ +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var exist = function(board, word) { + //word를 순회해서 board의 x,y를 조절하여, 값이 있으면 계속 true + const xLength = board[0].length; + const yLength = board.length + + // 체크 배열: 방문 여부를 저장. 각 DFS마다 새로 초기화될 필요는 없음 (DFS 내에서 백트래킹 처리하므로) + const check = Array.from({ length: yLength }, () => Array(xLength).fill(false)); + + + // 단어의 첫 글자와 일치하는 시작점을 모두 수집 + const startPoints = [] + for(let i = 0; i= yLength || + x < 0 || x >= xLength || + check[y][x] || + board[y][x] !== word[idx] + ) return false; + + check[y][x] = true + // 4방향 탐색 + for(let [dy,dx] of upDownLeftRight){ + //만약 타겟에 해당하는지를 확인을 먼저 해야할것같음! + if(dfs(y+dy,x+dx,idx+1)) return true //4방향에 대해서 모두 dfs를 진행한다. + + } + + //백트레킹 + check[y][x] = false; + return false + + } + return dfs(...startPoint,0) +} \ No newline at end of file From 402b6c08ec3fb6ca4b64be7db4d5847a7379e3a6 Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Sun, 27 Jul 2025 16:39:09 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20153.=20Find=20Minimum=20in=20Rotate?= =?UTF-8?q?d=20Sorted=20Array=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grapefruitgreentealoe.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js diff --git a/find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js b/find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js new file mode 100644 index 0000000000..5d1d18c3f4 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js @@ -0,0 +1,31 @@ + + +/* +회전한 데이터에서 제일 작은 값을 찾는 문제라는 것을 기억해야한다. +그렇게 때문에, left, right를 각각 0, nums.length -1 로 두어서, left와 right가 같아질때 탈출하고, 그 같아진 index에 대한 nums[index]를 찾아내면 될 것 같다. +*/ +/** + * + * @param {*} nums + * @returns + */ +function findMin(nums) { + let left = 0; + let right = nums.length - 1; + + while (left !== right) { + let mid = Math.floor((left + right) / 2); + + if (nums[mid] > nums[right]) { + // 최소값은 오른쪽에 있다 + left = mid + 1; + } else { + // 최소값은 왼쪽 구간에 있다 (mid도 포함 가능) + right = mid; + } + } + + return nums[left]; // 또는 nums[right]도 같음 +} +//시간복잡도 : 이진탐색을 썼으므로 O(logn) +//공간복잡도 : O(1) \ No newline at end of file From b5c79752589ff3bff388ef5588cb24b28980fa41 Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Mon, 28 Jul 2025 11:53:58 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20Merge=20Two=20Sorted=20Lists=20?= =?UTF-8?q?=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grapefruitgreentealoe.js | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 merge-two-sorted-lists/grapefruitgreentealoe.js diff --git a/merge-two-sorted-lists/grapefruitgreentealoe.js b/merge-two-sorted-lists/grapefruitgreentealoe.js new file mode 100644 index 0000000000..138a6d57d3 --- /dev/null +++ b/merge-two-sorted-lists/grapefruitgreentealoe.js @@ -0,0 +1,36 @@ +//두개의 정렬된 링크드 리스트 list1, list2의 Head를 받았다.(리스트가 아니라, 연결리스트의 헤드라는 것!) +/** + * 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} + */ +function mergeTwoLists( + list1, + list2, +) { + if (!(list1 && list2)) return list1 || list2; + if (list1.val < list2.val) { + list1.next = mergeTwoLists(list1.next, list2); + return list1; + } else { + list2.next = mergeTwoLists(list1, list2.next); + return list2; + } +} + +/* +list1.val이 list2.val보다 작으면 +list1.next 다음에 list2.val이 온다. +만약 아니라면, list2.next 다음에 list1의 Head를 붙여준다. +이렇게 next만 바꿔주면서 연결지어주는 것이다. + +시간 복잡도: O(log n) +공간 복잡도: O(h) +*/ \ No newline at end of file From f806b498942c938b84acc32cd742217d4bb5fbd5 Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Thu, 7 Aug 2025 19:54:48 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20maximum=20depth=20of=20binary=20tre?= =?UTF-8?q?e=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grapefruitgreentealoe.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 maximum-depth-of-binary-tree/grapefruitgreentealoe.js diff --git a/maximum-depth-of-binary-tree/grapefruitgreentealoe.js b/maximum-depth-of-binary-tree/grapefruitgreentealoe.js new file mode 100644 index 0000000000..75857cc5d6 --- /dev/null +++ b/maximum-depth-of-binary-tree/grapefruitgreentealoe.js @@ -0,0 +1,22 @@ +/** + * 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} + */ +var maxDepth = function (root) { + if (!root) return 0; + + // 왼쪽과 오른쪽 서브트리의 최대 깊이를 구한다. + const leftDepth = maxDepth(root.left); + const rightDepth = maxDepth(root.right); + + // 현재 노드의 깊이는 왼쪽과 오른쪽 깊이 중 큰 값에 1을 더한 값이다. + return Math.max(leftDepth, rightDepth) + 1; +}; From 81fa87edf2068f073e9c01fb2e861b482f6f9289 Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Mon, 11 Aug 2025 20:26:55 +0900 Subject: [PATCH 6/9] =?UTF-8?q?chore:=20=EA=B0=9C=ED=96=89=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coin-change/grapefruitgreentealoe.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/coin-change/grapefruitgreentealoe.js b/coin-change/grapefruitgreentealoe.js index 817f6c91f4..5d0542e32a 100644 --- a/coin-change/grapefruitgreentealoe.js +++ b/coin-change/grapefruitgreentealoe.js @@ -16,7 +16,6 @@ var coinChange = function(coins, amount) { return }else{ for(let c of coins){ - //여기서 dfs를 안들어가는 방법은 없을까? dfs(idx+coin,c) } } @@ -71,4 +70,4 @@ dfs를 쓰고 싶지 않다면, amount만큼의 for문을 돌면서 dp를 초기 시간복잡도: O(n * m) 공간 복잡도 : O(n) - */ \ No newline at end of file + */ From 78704ff63d409c92ea21cbd4a2d3a57ff64219da Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Mon, 11 Aug 2025 20:27:21 +0900 Subject: [PATCH 7/9] =?UTF-8?q?chore:=20=EA=B0=9C=ED=96=89=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js b/find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js index 5d1d18c3f4..e799346a2b 100644 --- a/find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js +++ b/find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js @@ -1,5 +1,3 @@ - - /* 회전한 데이터에서 제일 작은 값을 찾는 문제라는 것을 기억해야한다. 그렇게 때문에, left, right를 각각 0, nums.length -1 로 두어서, left와 right가 같아질때 탈출하고, 그 같아진 index에 대한 nums[index]를 찾아내면 될 것 같다. @@ -28,4 +26,4 @@ function findMin(nums) { return nums[left]; // 또는 nums[right]도 같음 } //시간복잡도 : 이진탐색을 썼으므로 O(logn) -//공간복잡도 : O(1) \ No newline at end of file +//공간복잡도 : O(1) From fdf3660f4487f6142f1008a00884a20cbf5886bf Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Mon, 11 Aug 2025 20:28:10 +0900 Subject: [PATCH 8/9] =?UTF-8?q?chore:=20=EA=B0=9C=ED=96=89=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- merge-two-sorted-lists/grapefruitgreentealoe.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/merge-two-sorted-lists/grapefruitgreentealoe.js b/merge-two-sorted-lists/grapefruitgreentealoe.js index 138a6d57d3..b78a521bc2 100644 --- a/merge-two-sorted-lists/grapefruitgreentealoe.js +++ b/merge-two-sorted-lists/grapefruitgreentealoe.js @@ -1,4 +1,4 @@ -//두개의 정렬된 링크드 리스트 list1, list2의 Head를 받았다.(리스트가 아니라, 연결리스트의 헤드라는 것!) +//두개의 정렬된 링크드 리스트 list1, list2의 Head를 받았다.(리스트가 아니라, 연결리스트의 헤드) /** * Definition for singly-linked list. * function ListNode(val, next) { @@ -33,4 +33,4 @@ list1.next 다음에 list2.val이 온다. 시간 복잡도: O(log n) 공간 복잡도: O(h) -*/ \ No newline at end of file +*/ From 298c8419f5381ceedd671fdf63cf4f7204fae759 Mon Sep 17 00:00:00 2001 From: grapefruitgreentealoe <76976331+grapefruitgreentealoe@users.noreply.github.com> Date: Mon, 11 Aug 2025 20:31:05 +0900 Subject: [PATCH 9/9] =?UTF-8?q?chore:=20=EC=8B=9C=EA=B0=84,=EA=B3=B5?= =?UTF-8?q?=EA=B0=84=EB=B3=B5=EC=9E=A1=EB=8F=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- word-search/grapefruitgreentealoe.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/word-search/grapefruitgreentealoe.js b/word-search/grapefruitgreentealoe.js index 3f2286929f..1eb8e767e1 100644 --- a/word-search/grapefruitgreentealoe.js +++ b/word-search/grapefruitgreentealoe.js @@ -59,4 +59,17 @@ function backTracking(startPoint,board,word,check){ } return dfs(...startPoint,0) -} \ No newline at end of file +} + +/* +시간 복잡도: O(m × n × 3^{L-1}) +- m × n: 시작점 후보 개수 +- 3^{L-1}: 첫 번째 이후로는 3방향으로만 뻗어나가는 경우의 수 + + +공간 복잡도: O(m × n) +- 방문 체크 배열: O(m × n) +- 재귀 호출 스택: 최악의 경우 단어 길이 L까지 깊어질 수 있으므로 O(L) + +여기서 m, n은 보드 크기, L은 단어 길이 + */