Skip to content

[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

Merged
merged 5 commits into from
Aug 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions find-minimum-in-rotated-sorted-array/jangwonyoon.js
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. 배열을 이진 탐색으로 탐색
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

각 풀이별로 복잡도 분석과 풀이법을 정리해주셔서 리뷰어 입장에서도 이해가 쉬웠고, 풀이하시는 과정에서도 공부가 많이 되셨을 것 같습니다!


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];
};
46 changes: 46 additions & 0 deletions maximum-depth-of-binary-tree/jangwonyoon.js
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;
};
41 changes: 41 additions & 0 deletions merge-two-sorted-lists/jangwonyoon.js
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 깊이까지 쌓일 수 있음
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

적어두신 것처럼 재귀로 풀면 콜 스택으로 인해 공간 복잡도가 O(n + m)이 됩니다! 그래서 저는 링크드리스트 문제는 반복문으로도 한 번 더 풀어보는 편인데요, 코드가 조금 더 복잡해지기는 하지만 공간 복잡도를 O(1)으로 줄일 수 있기 때문입니다. 여유가 되신다면 반복문으로도 풀어보시는 걸 추천드려요~!

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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;
}
};
123 changes: 123 additions & 0 deletions word-search/jangwonyoon.js
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; // 이미 방문했으면 탈락
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 주로 dfs에서 조건을 확인할 때 여러 조건들을 모두 or로 연결하곤 했었는데요, 각 조건이 각각 라인별로 적혀있으니 오히려 훨씬 가독성도 좋고 디버깅하기가 쉬워보이네요! 덕분에 배워갑니다~!


// 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;
};