Skip to content
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

[강희찬] WEEK 7 Solution #491

Merged
merged 5 commits into from
Sep 29, 2024
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
65 changes: 65 additions & 0 deletions longest-substring-without-repeating-characters/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* https://leetcode.com/problems/longest-substring-without-repeating-characters
* T.C. O(n^2)
* S.C. O(n)
*/
// function lengthOfLongestSubstring(s: string): number {
// let max = 0;
// for (let i = 0; i < s.length; i++) {
// const SET = new Set();
// let count = 0;
// for (let j = i; j < s.length; j++) {
// if (SET.has(s[j])) break;
// SET.add(s[j]);
// count += 1;
// max = Math.max(max, count);
// }
// }
// return max;
// }

/**
* T.C. O(n)
* S.C. O(n)
*/
// function lengthOfLongestSubstring(s: string): number {
// let left = 0;
// let right = 0;
// let max = 0;
// const SET = new Set();

// while (s[right]) {
// if (SET.has(s[right])) {
// SET.delete(s[left]);
// left++;
// } else {
// SET.add(s[right]);
// max = Math.max(SET.size, max);
// right++;
// }
// }

// return max;
// }

/**
* T.C. O(n)
* S.C. O(n)
*/
function lengthOfLongestSubstring(s: string): number {
let left = 0;
let right = 0;
let max = 0;
const MAP = new Map<string, number>();

while (right < s.length) {
if (MAP.has(s[right])) {
left = Math.max(MAP.get(s[right])! + 1, left);
Copy link
Contributor

Choose a reason for hiding this comment

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

와, Map을 사용해서 인덱스를 저장하니, left 인덱스를 하나씩 증가시키지 않고 한 번에 점프할 수가 있네요. 한 수 배워 갑니다! 🙇

}
MAP.set(s[right], right);
max = Math.max(max, right - left + 1);
right++;
}

return max;
}
66 changes: 66 additions & 0 deletions number-of-islands/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* https://leetcode.com/problems/number-of-islands
* T.C. O(m*n)
* S.C. O(m*n)
*/
// function numIslands(grid: string[][]): number {
// let count = 0;
// let dir = [[1, 0], [0, 1], [-1, 0], [0, -1]];

// function removeIsland(r: number, c: number) {
// if (r < 0 || r >= grid.length) return;
// if (c < 0 || c >= grid[0].length) return;
// if (grid[r][c] === '0') return;

// grid[r][c] = '0';
// for (let [dr, dc] of dir) {
// removeIsland(r + dr, c + dc);
// }
// return 1;
// }

// for (let r = 0; r < grid.length; r++) {
// for (let c = 0; c < grid[0].length; c++) {
// if (grid[r][c] === '0') continue;
// count++;
// removeIsland(r, c);
// }
// }

// return count;
// }

/**
* T.C. O(m*n)
* S.C. O(m*n)
*/
function numIslands(grid: string[][]): number {
let count = 0;
let dir = [[1, 0], [0, 1], [-1, 0], [0, -1]];

function removeIsland(r: number, c: number) {
const stack = [[r, c]];

while (stack.length) {
const [r, c] = stack.pop()!;
if (r < 0 || r >= grid.length) continue;
if (c < 0 || c >= grid[0].length) continue;
if (grid[r][c] === '0') continue;

grid[r][c] = '0';
for (let [dr, dc] of dir) {
stack.push([r + dr, c + dc]);
}
}
}

for (let r = 0; r < grid.length; r++) {
for (let c = 0; c < grid[0].length; c++) {
if (grid[r][c] === '0') continue;
count++;
removeIsland(r, c);
}
}

return count;
}
25 changes: 25 additions & 0 deletions reverse-linked-list/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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;
}
}

/**
* https://leetcode.com/problems/reverse-linked-list
* T.C. O(n)
* S.C. O(1)
*/
function reverseList(head: ListNode | null): ListNode | null {
let prev: ListNode | null = null;
let current: ListNode | null = head;
while (current !== null) {
const next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}
78 changes: 78 additions & 0 deletions set-matrix-zeroes/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* https://leetcode.com/problems/set-matrix-zeroes
* T.C. O(r * c)
* S.C. O(r + c)
*/
function setZeroes(matrix: number[][]): void {
const r = matrix.length;
const c = matrix[0].length;

const zeroRows = new Set<number>();
const zeroCols = new Set<number>();

for (let i = 0; i < r; i++) {
for (let j = 0; j < c; j++) {
if (matrix[i][j] === 0) {
zeroRows.add(i);
zeroCols.add(j);
}
}
}

for (let i = 0; i < r; i++) {
for (let j = 0; j < c; j++) {
if (zeroRows.has(i) || zeroCols.has(j)) {
matrix[i][j] = 0;
}
}
}
}

/**
* T.C. O(r * c)
* S.C. O(1)
*/
function setZeroes(matrix: number[][]): void {
const r = matrix.length;
const c = matrix[0].length;

let firstRowHasZero = false;
let firstColHasZero = false;

if (matrix[0].some((val) => val === 0)) {
firstRowHasZero = true;
}

if (matrix.some((row) => row[0] === 0)) {
firstColHasZero = true;
}

for (let i = 1; i < r; i++) {
for (let j = 1; j < c; j++) {
if (matrix[i][j] === 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}

for (let i = 1; i < r; i++) {
if (matrix[i][0] === 0) {
matrix[i].fill(0);
}
}

for (let j = 1; j < c; j++) {
if (matrix[0][j] === 0) {
matrix.forEach((row) => (row[j] = 0));
}
}
Comment on lines +59 to +69
Copy link
Contributor

Choose a reason for hiding this comment

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

(질문) 반복문을 하나로 합쳐 진행해도 좋을 것 같은데 두 개로 나누신 이유가 따로 있으실까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

넵 질문주셔서 감사합니다!

matrix의 가로, 세로 사이즈가 다를 수 있어서 분리 하였는데, 취향에 따라 아래와 같이 표현할 수는 있을 것 같습니다.

for (let i = 1; i < Math.max(r, c); i++) {
  if (matrix[i]?.[0] === 0) matrix[i].fill(0);
  if (matrix[0]?.[i] === 0) matrix.forEach((row) => (row[i] = 0));
}

다만 지극히 제 주관적으로, 위 코드는 전체 라인 수는 줄어들지만 조건이나 처리가 다소 지저분하다고 느껴져서 두 개의 순회로 분리하였습니다!

Copy link
Contributor

Choose a reason for hiding this comment

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

아 네 희찬님, 제가 생각했던 코드는 요런 방식이었습니다!
이 방법이 가독성이 크게 떨어지지는 않는 것 같아서 소소하게 코멘트 남기려 했습니다!

Suggested change
for (let i = 1; i < r; i++) {
if (matrix[i][0] === 0) {
matrix[i].fill(0);
}
}
for (let j = 1; j < c; j++) {
if (matrix[0][j] === 0) {
matrix.forEach((row) => (row[j] = 0));
}
}
for (let i = 1; i < r; i++) {
for (let j = 1; j < c; j++) {
if (matrix[i][0] === 0 || matrix[0][j] === 0) {
matrix[i][j] = 0;
}
}
}


if (firstRowHasZero) {
matrix[0].fill(0);
}

if (firstColHasZero) {
matrix.forEach((row) => (row[0] = 0));
}
}
65 changes: 65 additions & 0 deletions unique-paths/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Solution 1. recursive - failed with Stack Overflow
*/
function uniquePaths(m: number, n: number): number {
function factorialMemo() {
const cache = [0, 1];
return function factorial(n: number) {
if (cache[n]) return cache[n];
cache[n] = n * factorial(n - 1);
return cache[n];
};
}

const factorial = factorialMemo();
const total = m + n - 2;
const right = m - 1;
return Math.round(
factorial(total) / (factorial(right) * factorial(total - right))
);
}

/**
* Solution 2. for loop (with some 야매.. but it works)
* https://leetcode.com/problems/unique-paths
* T.C. O(m + n)
* S.C. O(m + n)
*/
function uniquePaths(m: number, n: number): number {
function factorialMemo() {
const cache = [1, 1];
return function factorial(n: number) {
if (cache[n]) return cache[n];
let result = cache[cache.length - 1];
for (let i = cache.length; i <= n; i++) {
result = result * i;
cache[i] = result;
}
return result;
};
}

const factorial = factorialMemo();
const total = m + n - 2;
const right = m - 1;
return Math.round(
factorial(total) / (factorial(right) * factorial(total - right))
);
}

/**
* Solution 3. DP
* T.C. O(m * n)
* S.C. O(m * n)
*/
function uniquePaths(m: number, n: number): number {
const dp: number[][] = Array.from({ length: m }, () => Array(n).fill(1));

for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}

return dp[m - 1][n - 1];
}