Skip to content

[soobing] WEEK09 Solutions #1525

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 2, 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
52 changes: 52 additions & 0 deletions linked-list-cycle/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* 문제 설명
* - 링크드리스트 내에 cycle이 존재하는지 확인하는 문제
*
* 아이디어
* - 링크드리스트를 끝까지 순회하면서 방문한 노드를 저장하고, 방문한 노드가 존재하면 cycle이 존재하는 것으로 판단
* - 시간복잡도: O(n), 공간복잡도 O(n)
*
*/

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 hasCycle(head: ListNode | null): boolean {
const visited = new Set<ListNode>();

while (head) {
if (visited.has(head)) {
return true;
} else {
visited.add(head);
head = head.next;
}
}
return false;
}

/**
* 공간복잡도 O(1) 로도 풀 수 있음.
*/

// function hasCycle(head: ListNode | null): boolean {
// let slow = head;
// let fast = head;

// while (fast && fast.next) {
// slow = slow!.next;
// fast = fast.next.next!;

// if (slow === fast) {
// return true;
// }
// }

// return false;
// }
22 changes: 22 additions & 0 deletions maximum-product-subarray/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* 문제 설명
* - 배열에서 연속된 부분 배열의 곱이 가장 큰 값을 찾는 문제
*
* 아이디어
* - 1) 브루트포스 O(n^2)
* - 2) DP 최적화 O(n)
* - 매 index마다, 현재까지 max 곱, min 곱을 찾고 최대값을 갱신
*/
function maxProduct(nums: number[]): number {
let maxSoFar = nums[0];
Copy link
Contributor

Choose a reason for hiding this comment

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

모든 경우를 한 번에 고려하는 깔끔한 접근입니다 👍
초기에 빈 배열 예외처리가 있으면 더 좋을것 같아요!

let max = nums[0];
let min = nums[0];

for (let i = 1; i < nums.length; i++) {
const candidate = [nums[i], max * nums[i], min * nums[i]];
max = Math.max(...candidate);
min = Math.min(...candidate);
maxSoFar = Math.max(maxSoFar, max);
}
return maxSoFar;
}
54 changes: 54 additions & 0 deletions minimum-window-substring/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* 문제 설명
* - 주어진 문자열 s에서 주어진 문자열 t의 모든 문자를 포함하는 최소 윈도우를 찾는 문제
*
* 아이디어
* - 슬라이딩 윈도우 + 해시맵(need, window)을 이용하여 풀이한다.
* - 오른쪽 포인터를 먼저 이동하고, 이미 모두 포함되어 있는 경우 왼쪽 포인터를 이동하여 최소 윈도우를 찾는다.
*
*/
function minWindow(s: string, t: string): string {
if (t.length > s.length) return "";

const need = new Map<string, number>();
const window = new Map<string, number>();

for (const char of t) {
need.set(char, (need.get(char) || 0) + 1);
}

let have = 0;
let needSize = need.size;
let res = [-1, -1];
let resLen = Infinity;

let left = 0;

for (let right = 0; right < s.length; right++) {
const c = s[right];
window.set(c, (window.get(c) || 0) + 1);

if (need.has(c) && window.get(c) === need.get(c)) {
have++;
}

while (have === needSize) {
const currentResLen = right - left + 1;
if (currentResLen < resLen) {
res = [left, right];
resLen = currentResLen;
}

const lChar = s[left];
window.set(lChar, window.get(lChar)! - 1);

if (need.has(lChar) && window.get(lChar)! < need.get(lChar)!) {
have--;
}
left++;
}
}

const [start, end] = res;
return resLen === Infinity ? "" : s.slice(start, end + 1);
}
64 changes: 64 additions & 0 deletions pacific-atlantic-water-flow/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* 문제 설명
* - 비가 내렸을 때, 태평양과 대서양 모두로 물이 흐를 수 있는 지점을 찾아 반환하는 문제입니다.
* 아이디어
* 1) BFS/DFS
* - 각 바다에서 역방향으로 물이 도달할 수 있는 셀을 탐색한 후, 두 바다 모두에 도달 가능한 셀의 교집합 구하기
Copy link
Contributor

@YoungSeok-Choi YoungSeok-Choi May 31, 2025

Choose a reason for hiding this comment

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

안녕하세요!
요 문제를 반대로 바다에서 부터 시작하는 방식으로 접근해 풀이해 보셨군요...!

저는 모든 셀에 대해서 양 바다로 모두 닿을 수 있는지 여부를 판단하려고 모든 셀 * 2 번씩 dfs 를 돌렸었는데
이런 아이디어를 떠올리게 된 뭐랄까요 생각의 과정..? 를 간단히 설명해주실 수 있을까요!?

(어떤 부분을 보고 이렇게 접근해볼 수도 있겠다.. 라는 식의 느낌입니다 🤣 뭔가 콕찝어서 설명을 못하겠네요ㅠ)

+) 알고리즘 문제를 풀이하실 때 풀이 아이디어를 떠올리시는 포인트? 같은것도 만약 있으시다면 알려주시면 감사히 배워가겠습니다!

*
*/

function pacificAtlantic(heights: number[][]): number[][] {
const m = heights.length;
const n = heights[0].length;

const pacific = Array.from({ length: m }, () => Array(n).fill(false));
const atlantic = Array.from({ length: m }, () => Array(n).fill(false));

const directions = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
];

function dfs(r: number, c: number, visited: boolean[][], prevHeight: number) {
if (
r < 0 ||
c < 0 ||
r >= m ||
c >= n ||
visited[r][c] ||
heights[r][c] < prevHeight
)
return;

visited[r][c] = true;

for (const [dr, dc] of directions) {
dfs(r + dr, c + dc, visited, heights[r][c]);
}
}

// 태평양 DFS
for (let i = 0; i < m; i++) {
dfs(i, 0, pacific, heights[i][0]); // 왼쪽
dfs(i, n - 1, atlantic, heights[i][n - 1]); // 오른쪽
}

for (let j = 0; j < n; j++) {
dfs(0, j, pacific, heights[0][j]); // 위쪽
dfs(m - 1, j, atlantic, heights[m - 1][j]); // 아래쪽
}

const result: number[][] = [];

for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (pacific[i][j] && atlantic[i][j]) {
result.push([i, j]);
}
}
}

return result;
}
16 changes: 16 additions & 0 deletions sum-of-two-integers/soobing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* 문제 설명
* - 두 정수의 합을 반환하는 문제 (비트 연산을 통해서)
*
* 아이디어
* - 반올림은 AND(&) + 왼쪽 shift 1, 덧셈은 XOR(^) 연산을 통해서 한다.
* - 반올림이 0이 될 때까지 반복한다. ⭐️
*/
function getSum(a: number, b: number): number {
while (b !== 0) {
const carry = (a & b) << 1;
a = a ^ b;
b = carry;
}
return a;
}