-
-
Notifications
You must be signed in to change notification settings - Fork 247
[jangwonyoon] WEEK04 solutions #1835
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
Changes from all commits
a8b9294
f1a1e78
9c26162
e202245
1381ad8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 깊이까지 쌓일 수 있음 | ||
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. 적어두신 것처럼 재귀로 풀면 콜 스택으로 인해 공간 복잡도가 O(n + m)이 됩니다! 그래서 저는 링크드리스트 문제는 반복문으로도 한 번 더 풀어보는 편인데요, 코드가 조금 더 복잡해지기는 하지만 공간 복잡도를 O(1)으로 줄일 수 있기 때문입니다. 여유가 되신다면 반복문으로도 풀어보시는 걸 추천드려요~! 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. 오오 감사합니다!! 반복문으로더 풀어볼게요 |
||
*/ | ||
|
||
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; | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; // 이미 방문했으면 탈락 | ||
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. 저는 주로 dfs에서 조건을 확인할 때 여러 조건들을 모두 |
||
|
||
// 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; | ||
}; |
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.
각 풀이별로 복잡도 분석과 풀이법을 정리해주셔서 리뷰어 입장에서도 이해가 쉬웠고, 풀이하시는 과정에서도 공부가 많이 되셨을 것 같습니다!