-
-
Notifications
You must be signed in to change notification settings - Fork 247
[grapefruitgreentealoe] WEEK 04 Solutions #1818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
grapefruitgreentealoe
merged 9 commits into
DaleStudy:main
from
grapefruitgreentealoe:week4
Aug 16, 2025
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
c47adc0
feat: coin-change 풀이
grapefruitgreentealoe 21dedca
feat: word-search 풀이
grapefruitgreentealoe 402b6c0
feat: 153. Find Minimum in Rotated Sorted Array 풀이
grapefruitgreentealoe b5c7975
feat: Merge Two Sorted Lists 풀이
grapefruitgreentealoe f806b49
feat: maximum depth of binary tree 풀이
grapefruitgreentealoe 81fa87e
chore: 개행추가
grapefruitgreentealoe 78704ff
chore: 개행추가
grapefruitgreentealoe fdf3660
chore: 개행추가
grapefruitgreentealoe 298c841
chore: 시간,공간복잡도 추가
grapefruitgreentealoe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
|
||
//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(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 <amount+1; i++){ | ||
for(let coin of coins){ | ||
if(i-coin >= 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) | ||
*/ |
29 changes: 29 additions & 0 deletions
29
find-minimum-in-rotated-sorted-array/grapefruitgreentealoe.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
회전한 데이터에서 제일 작은 값을 찾는 문제라는 것을 기억해야한다. | ||
그렇게 때문에, 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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
Comment on lines
+34
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LinkedList의 정렬을 위해서는 각 list1, list2의 모든 요소를 순회해야 하고, 따로 메모리를 사용하지 않으신것 같은데 시간 복잡도 O(m+n), m은 list1의 길이, n은 list2의 길이 / 공간 복잡도 O(1) 라고 생각되요! |
||
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** | ||
* @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<xLength;i++){ | ||
for(let j = 0; j<yLength;j++){ | ||
if(board[j][i] == word[0]){ | ||
startPoints.push([j,i]) | ||
} | ||
} | ||
} | ||
// 각 시작점에서 DFS 시도 | ||
for(let startPoint of startPoints){ | ||
// 잘못된 길로 가는 경우도 있기 때문에 백트렉킹은 무조건 필요하다. | ||
if(backTracking(startPoint,board,word,check)) return true | ||
} | ||
|
||
return false | ||
}; | ||
|
||
function backTracking(startPoint,board,word,check){ | ||
const xLength = board[0].length; | ||
const yLength = board.length | ||
const upDownLeftRight = [[-1,0],[1,0],[0,-1],[0,1]] | ||
//스타트 포인트부터 해서, 완성이 가능한지를 dfs를 통해서 진행한다. | ||
//idx는 현재 확인해야할 word의 idx이다. | ||
function dfs(y,x,idx){ | ||
if(idx == word.length) return true | ||
|
||
if(y < 0 || y >= 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) | ||
} | ||
|
||
/* | ||
시간 복잡도: O(m × n × 3^{L-1}) | ||
- m × n: 시작점 후보 개수 | ||
- 3^{L-1}: 첫 번째 이후로는 3방향으로만 뻗어나가는 경우의 수 | ||
|
||
|
||
공간 복잡도: O(m × n) | ||
- 방문 체크 배열: O(m × n) | ||
- 재귀 호출 스택: 최악의 경우 단어 길이 L까지 깊어질 수 있으므로 O(L) | ||
|
||
여기서 m, n은 보드 크기, L은 단어 길이 | ||
*/ |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Binary Search에서 흔히 사용하는 식이네요!
해당 식과 관련하여 공유드리고 싶은 정보가 있어서 디스코드로 공유해 둘께요 :)