Skip to content

[soobing] WEEK 10 Solutions #1553

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
Jun 6, 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
37 changes: 37 additions & 0 deletions course-schedule/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* 문제 해설
* - 그래프에 사이클이 있는지 없는지 확인하는 문제
*
* 아이디어
* 1) 그래프 탐색 -> DFS, BFS
* - 그래프를 탐색하며 사이클이 있는지 없는지 확인한다.
* - 현재 경로에 이미 방문한 노드를 다시 만나면 사이클 발생. = 1
*/

function canFinish(numCourses: number, prerequisites: number[][]): boolean {
const graph = new Map<number, number[]>();
const visited: number[] = new Array(numCourses).fill(0); // 0: 안 다녀옴, 1: 사이클 확인 증(방문 중), 2: 사이클 없음 확인 완료

// 그래프 생성
for (const [course, preCourse] of prerequisites) {
if (!graph.has(course)) graph.set(course, []);
graph.get(course)!.push(preCourse);
}

function hasCycle(index: number) {
if (visited[index] === 1) return true;
if (visited[index] === 2) return false;

visited[index] = 1;
for (const preCourse of graph.get(index) || []) {
if (hasCycle(preCourse)) return true;
}
visited[index] = 2;
return false;
}

for (let i = 0; i < numCourses; i++) {
if (hasCycle(i)) return false;
}
return true;
}
64 changes: 64 additions & 0 deletions invert-binary-tree/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* 문제 설명
* - 이진 트리를 반전시키는 문제
*
* 아이디어
* 1) DFS / BFS 로 탐색하면서 반전시키기
* - 시간 복잡도 O(n): 모든 노드 한번씩 방문
* - 공간 복잡도 DFS의 경우 O(h), BFS의 경우 O(2/n) -> 마지막 레벨의 노드 수
*/

class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
this.val = val === undefined ? 0 : val;
this.left = left === undefined ? null : left;
this.right = right === undefined ? null : right;
}
}

function invertTree(root: TreeNode | null): TreeNode | null {
if (!root) return null;

const left = invertTree(root.left);
const right = invertTree(root.right);

root.left = right;
root.right = left;

return root;
}

/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/

function invertTreeBFS(root: TreeNode | null): TreeNode | null {
const queue: (TreeNode | null)[] = [root];

while (queue.length > 0) {
const current = queue.shift();
if (current) {
const left = current.left;
const right = current.right;
current.left = right;
current.right = left;

queue.push(left);
queue.push(right);
}
}
return root;
}
17 changes: 17 additions & 0 deletions jump-game/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* 문제 해설
* - 현재 위치에서 최대 점프할 수 있는 갯수를 담고 있는 배열, 마지막 항목에 도달이 가능한지 반환하는 문제
*
* 아이디어
* 1) 그리디 알고리즘
* - 배열을 쭉 순회하면서 다음 이동 가능한 횟수를 비교하여 다음 항목으로 이동이 가능한지 체크, 없다면 false 반환.
* - 일단 현재까지 왔다면 이후에 최대로 갈 수 있는 값을 업데이트.
*/
function canJump(nums: number[]): boolean {
let reachable = 0;
for (let i = 0; i < nums.length; i++) {
if (i > reachable) return false;
reachable = Math.max(reachable, i + nums[i]);
}
return true;
}
56 changes: 56 additions & 0 deletions merge-k-sorted-lists/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* 문제 설명
* - k개의 정렬된 링크드 리스트 병합하기
*
* 아이디어
* 1) 병합정렬 -> 대표적인 분할 정복(Divide and Conquer) 문제
* - 두 리스트를 병합할 수 있는 함수를 계속해서 적용한다.
* - 두 링크드 리스트 병합하는 예제
* ㄴ @link https://leetcode.com/problems/merge-two-sorted-lists/description/
*
*/
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/

class ListNode {
val: number;
next: ListNode | null;
constructor(val?: number, next?: ListNode | null) {
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
}

function mergeList(list1: ListNode | null, list2: ListNode | null) {
const dummy = new ListNode(0);
let current = dummy;

while (list1 && list2) {
if (list1.val <= list2.val) {
current.next = list1;
list1 = list1.next;
} else {
current.next = list2;
list2 = list2.next;
}
current = current.next;
}
current.next = list1 || list2;

return dummy.next;
}

function mergeKLists(lists: Array<ListNode | null>): ListNode | null {
return lists.reduce((acc, current) => {
return mergeList(acc, current);
}, null);
}
38 changes: 38 additions & 0 deletions search-in-rotated-sorted-array/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* 문제 설명
* - 회전된 정렬된 배열에서 타겟 값을 찾는 문제
* - 이진 탐색의 응용 버전
*
* 아이디어
* 1) 변형된 이진 탐색 사용
* - 중간 값과 왼쪽, 끝 값을 비교하여 왼쪽 정렬 영역인지 오른쪽 정렬 영역인지 확인
*/

function search(nums: number[], target: number): number {
let left = 0;
let right = nums.length - 1;

while (left <= right) {
const mid = Math.floor((left + right) / 2);

if (nums[mid] === target) return mid;

// mid가 왼쪽 정렬에 포함
if (nums[mid] >= nums[left]) {
if (target >= nums[left] && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
// mid가 오른쪽 정렬에 포함
else {
if (target < nums[mid] && target <= nums[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}