Skip to content

Commit

Permalink
Merge pull request #481 from wogha95/main
Browse files Browse the repository at this point in the history
[재호] WEEK 07 Solutions
  • Loading branch information
wogha95 authored Sep 28, 2024
2 parents c25a352 + 570f2da commit 07b18e7
Show file tree
Hide file tree
Showing 5 changed files with 373 additions and 0 deletions.
51 changes: 51 additions & 0 deletions longest-substring-without-repeating-characters/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* TC: O(S)
* right의 S만큼 순회 + left의 S만큼 순회
* (각 순회의 곱이 μ•„λ‹Œ 합인 μ΄μœ λŠ” right 순회 λ™μ•ˆ left의 μ΅œλŒ€ μˆœνšŒκ°€ S이기 λ•Œλ¬Έμž…λ‹ˆλ‹€.)
*
* SC: O(S)
* usedCharacter에 S만큼 λ“€μ–΄κ°ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.
*
* S: s.length
*/

/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function (s) {
// 1. μ‚¬μš©λœ 문자λ₯Ό κΈ°λ‘ν•˜κΈ° μœ„ν•œ set
const usedCharacter = new Set();

// 2. μ •λ‹΅ μ œμΆœμ„ μœ„ν•œ λΆ€λΆ„λ¬Έμžμ—΄ μ΅œλŒ€ 길이
let maxLength = 0;

// 3. 순회λ₯Ό μœ„ν•œ 포인터 + 각 indexμ—μ„œ μ΅œλŒ€ λ¬Έμžμ—΄κΈΈμ΄λ₯Ό κ΅¬ν•˜κΈ° μœ„ν•œ λ³€μˆ˜
let left = 0;
let right = 0;

while (left <= right && right < s.length) {
// 4. [right] λ¬Έμžκ°€ μ‚¬μš©λ˜μ—ˆμœΌλ©΄
if (usedCharacter.has(s[right])) {
// 5. μ‚¬μš©λœ 문자λ₯Ό λ°œκ²¬ν•˜κΈ° μ „κΉŒμ§€ left 이동 (+ μ‚¬μš©λœ [left] 문자 기둝 제거)
while (s[left] !== s[right]) {
usedCharacter.delete(s[left]);
left += 1;
}

// 6. [right] λ¬Έμžμ™€ [left] λ¬Έμžκ°€ λ™μΌν•˜λ―€λ‘œ left만 이동
left += 1;
} else {
// 7. [right] λ¬Έμžκ°€ λ―Έμ‚¬μš©λ˜μ—ˆμœΌλ©΄ 기둝 μΆ”κ°€
usedCharacter.add(s[right]);
}

// 8. μ€‘λ³΅μ—†λŠ” λΆ€λΆ„λ¬Έμžμ—΄ μ΅œλŒ€ 길이 κ°±μ‹ 
maxLength = Math.max(maxLength, right - left + 1);

// 9. λ‹€μŒ 문자둜 이동
right += 1;
}

return maxLength;
};
80 changes: 80 additions & 0 deletions number-of-islands/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* TC: O(ROW * COLUMN)
* 주어진 grid λ°°μ—΄ 전체 순회 + (μ΅œμ•…μ˜ 경우 queueμ—μ„œ grid 전체 순회)
*
* SC: O(ROW * COLUMN)
* queueμ—μ„œ μ΅œλŒ€ grid만큼 순회
*
* ROW: grid.length, COLUMN: grid[0].length
*/

/**
* @param {character[][]} grid
* @return {number}
*/
var numIslands = function (grid) {
const LAND = "1";
const VISITED_LAND = "#";
const ROW = grid.length;
const COLUMN = grid[0].length;

// 1. μƒν•˜μ’Œμš° λ°©ν–₯ν‚€
const DIRECTION = [
{ r: 0, c: 1 },
{ r: 1, c: 0 },
{ r: 0, c: -1 },
{ r: -1, c: 0 },
];

let numberOfIslands = 0;

// 2. 전체 μˆœνšŒν•˜λ©΄μ„œ
for (let row = 0; row < ROW; row++) {
for (let column = 0; column < COLUMN; column++) {
// 3. LANDλ₯Ό λ°œκ²¬ν•˜λ©΄ λ°©λ¬Έν•œ μ„¬μœΌλ‘œ ν‘œμ‹œ(bfs)ν•˜κ³  μ„¬κ°―μˆ˜ κ°±μ‹ 
if (grid[row][column] === LAND) {
bfs(row, column);
numberOfIslands += 1;
}
}
}

return numberOfIslands;

function bfs(startRow, startColumn) {
// 4. μ‹œμž‘μ’Œν‘œ queue에 λ„£κ³  λ°©λ¬Έ ν‘œμ‹œ
const queue = [[startRow, startColumn]];
grid[startRow][startColumn] = VISITED_LAND;

while (queue.length > 0) {
const [row, column] = queue.shift();

// 5. μƒν•˜μ’Œμš°μ˜ μ’Œν‘œλ₯Ό 가지고
for (const direction of DIRECTION) {
const nextRow = row + direction.r;
const nextColumn = column + direction.c;

// 6. μœ νš¨ν•œ μ’Œν‘œ && λ―Έλ°©λ¬Έ μœ‘μ§€μΈμ§€ 확인
if (
isValidPosition(nextRow, nextColumn) &&
grid[nextRow][nextColumn] === LAND
) {
// 7. queue에 μΆ”κ°€ν•˜κ³  λ°©λ¬Έ ν‘œμ‹œ
grid[nextRow][nextColumn] = VISITED_LAND;
queue.push([nextRow, nextColumn]);
}
}
}
}

// 8. 주어진 2차원 λ°°μ—΄μ˜ μœ νš¨ν•œ μ’Œν‘œμΈμ§€ ν™•μΈν•˜λŠ” ν•¨μˆ˜
function isValidPosition(row, column) {
if (row < 0 || ROW <= row) {
return false;
}
if (column < 0 || COLUMN <= column) {
return false;
}
return true;
}
};
69 changes: 69 additions & 0 deletions reverse-linked-list/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* 2μ°¨
* Tonyλ‹˜ 풀이 μ°Έκ³ ν•΄μ„œ SC κ°œμ„ 
*
* TC: O(N)
* SC: O(1)
* μˆœνšŒλ™μ•ˆ λ…Έλ“œ μƒμ„±ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ κ³΅κ°„λ³΅μž‘λ„κ°€ μƒμˆ˜λ‹€.
*
* N: linked-list length
*/

/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function (head) {
let pointer = null;

while (head !== null) {
let temp = head.next;
head.next = pointer;
pointer = head;
head = temp;
}

return pointer;
};

/**
* 1μ°¨
* TC: O(N)
* linked-list 길이 만큼 순회
*
* SC: O(N)
* linked-list 길이만큼 생성
*
* N: linked-list length
*/

/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function (head) {
let pointer = null;

while (head) {
// 1. μ •λ‹΅ 리슀트의 맨 μ•žμ— μƒˆλ‘œμš΄ λ…Έλ“œλ₯Ό μΆ”κ°€
pointer = new ListNode(head.val, pointer);
// 2. headλŠ” λ‹€μŒ λ…Έλ“œλ‘œ 이동
head = head.next;
}

return pointer;
};
46 changes: 46 additions & 0 deletions set-matrix-zeroes/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* TC: O(ROW * COLUMN)
* SC: O(1)
*/

/**
* @param {number[][]} matrix
* @return {void} Do not return anything, modify matrix in-place instead.
*/
var setZeroes = function (matrix) {
const ROW = matrix.length;
const COLUMN = matrix[0].length;
const MARK = "#";

// 1. 0인 μš”μ†Œμ˜ κ°€λ‘œ, μ„Έλ‘œλ₯Ό νŠΉμ •λ¬Έμžλ‘œ λ³€κ²½
for (let row = 0; row < ROW; row++) {
for (let column = 0; column < COLUMN; column++) {
if (matrix[row][column] === 0) {
changeToMark(row, column);
}
}
}

// 2. νŠΉμ •λ¬Έμžλ₯Ό λͺ¨λ‘ 0으둜 λ³€κ²½
for (let row = 0; row < ROW; row++) {
for (let column = 0; column < COLUMN; column++) {
if (matrix[row][column] === MARK) {
matrix[row][column] = 0;
}
}
}

// 3. νŠΉμ • μ’Œν‘œμ˜ κ°€λ‘œ, μ„Έλ‘œλ₯Ό char문자둜 λ³€κ²½ (λŒ€μ‹  0인 μš”μ†ŒλŠ” λ³€κ²½ν•˜μ§€ μ•ŠμŒ)
function changeToMark(row, column) {
for (let r = 0; r < ROW; r++) {
if (matrix[r][column] !== 0) {
matrix[r][column] = MARK;
}
}
for (let c = 0; c < COLUMN; c++) {
if (matrix[row][c] !== 0) {
matrix[row][c] = MARK;
}
}
}
};
127 changes: 127 additions & 0 deletions unique-paths/wogha95.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
* 3μ°¨ (μ‹œκ°„, 곡간 λ³΅μž‘λ„ κ°œμ„ )
* λ™μΌν•œ downλ°©ν–₯, rightλ°©ν–₯λ“€ μ€‘μ—μ„œ λ‚˜μ—΄ν•˜λŠ” 방법
* 즉, ((m - 1) + (n - 1))! / ((m - 1)! * (n - 1)!)
* (+ νŒ©ν† λ¦¬μ–Όμ˜ μˆ˜λŠ” 맀우 λΉ λ₯΄κ²Œ μ»€μ§€λ―€λ‘œ 쀑간 λ‚˜λˆ—μ…ˆμ΄ κ°€λŠ₯ν• λ•Œλ§ˆλ‹€ λ‚˜λˆ„μ–΄μ„œ integer λ²”μœ„λ₯Ό λ„˜μ§€ μ•Šλ„λ‘ 방지)
*
* TC: O(M + N)
* 1λΆ€ν„° μ΅œλŒ€ (M - 1) + (N - 1)κΉŒμ§€ 순회
*
* SC: O(1)
* κ³„μ‚°μ˜ κ²°κ³Ό λ³€μˆ˜κ°€ m, nκ³Ό λ¬΄κ΄€ν•˜λ―€λ‘œ μƒμˆ˜μ˜ κ³΅κ°„λ³΅μž‘λ„
*/

/**
* @param {number} m
* @param {number} n
* @return {number}
*/
var uniquePaths = function (m, n) {
// 1. downλ°©ν–₯, rightλ°©ν–₯의 수
const NUMBER_OF_DOWN = m - 1;
const NUMBER_OF_RIGHT = n - 1;

// 2. factorial 계산을 μœ„ν•œ λ³€μˆ˜
let result = 1;
let factorialOfDown = 1;
let factorialOfRight = 1;

// 3. 'downλ°©ν–₯ 수 + rightλ°©ν–₯ 수'만큼 μˆœνšŒν•˜λ©΄μ„œ
for (let number = 1; number <= NUMBER_OF_DOWN + NUMBER_OF_RIGHT; number++) {
result *= number;

// 4. factorial 값듀이 컀지지 μ•Šλ„λ‘ λ‚˜λˆŒμˆ˜ μžˆμ„λ•Œλ§ˆλ‹€ λ‚˜λˆ” (factorial of down)
if (number <= NUMBER_OF_DOWN) {
factorialOfDown *= number;
if (result % factorialOfDown === 0) {
result /= factorialOfDown;
factorialOfDown = 1;
}
}

// 5. factorial 값듀이 컀지지 μ•Šλ„λ‘ λ‚˜λˆŒμˆ˜ μžˆμ„λ•Œλ§ˆλ‹€ λ‚˜λˆ” (factorial of right)
if (number <= NUMBER_OF_RIGHT) {
factorialOfRight *= number;
if (result % factorialOfRight === 0) {
result /= factorialOfRight;
factorialOfRight = 1;
}
}
}

return result / factorialOfDown / factorialOfRight;
};

/**
* 2μ°¨ (κ³΅κ°„λ³΅μž‘λ„ κ°œμ„ )
* 이전 ν’€μ΄μ—μ„œ λͺ¨λ“  ν–‰μ˜ 경둜수λ₯Ό κΈ°μ–΅ν•  ν•„μš”κ°€ μ—†λŠ” 점을 ν™œμš©
*
* TC: O(M * N)
* 경둜 수λ₯Ό κΈ°λ‘ν•˜κΈ° μœ„ν•œ Nλ°°μ—΄ 순회 * (M - 1)
*
* SC: O(N)
* 경둜수 기둝을 μœ„ν•œ 1차원 λ°°μ—΄
*/

/**
* @param {number} m
* @param {number} n
* @return {number}
*/
var uniquePaths = function (m, n) {
// 1. μ΅œμƒλ‹¨μ˜ κ²½λ‘œμˆ˜λŠ” λͺ¨λ‘ 1
const numberOfPaths = new Array(n).fill(1);

for (let row = 1; row < m; row++) {
// 2. 각 μ’Œν‘œμ˜ κ²½λ‘œμˆ˜λŠ” ν˜„μ’Œν‘œ(1μ°¨ ν’€μ΄μ˜ row-1)와 μ’ŒμΈ‘μ’Œν‘œ(1μ°¨ ν’€μ΄μ˜ column-1)의 ν•©
for (let column = 1; column < n; column++) {
numberOfPaths[column] += numberOfPaths[column - 1];
}
}

return numberOfPaths[n - 1];
};

/**
* 1μ°¨
* 각 μ’Œν‘œμ˜ 경둜수λ₯Ό κΈ°λ‘ν•˜μ—¬ dp둜 풀이
* ν˜„μ’Œν‘œκΉŒμ§€μ˜ 경둜수 = μƒλ‹¨μ’Œν‘œμ—μ„œ 온 경우 + μ’ŒμΈ‘μ’Œν‘œμ—μ„œ 온 경우
* dp[row][column] = dp[row - 1][column] + dp[row][column - 1]
*
*
* TC: O(M * N)
* 경둜수λ₯Ό κΈ°λ‘ν•œ 2차원 배열을 전체 순회
*
* SC: O(M * N)
* 경둜수 기둝을 μœ„ν•œ 2차원 λ°°μ—΄
*/

/**
* @param {number} m
* @param {number} n
* @return {number}
*/
var uniquePaths = function (m, n) {
// 1. 각 μ’Œλ£ŒκΉŒμ§€μ˜ 경둜수λ₯Ό κΈ°λ‘ν•˜κΈ° μœ„ν•œ λ°°μ—΄
const numberOfPaths = new Array(m).fill(new Array(n).fill(0));

// 2. μ΅œμ’ŒμΈ‘μ— μžˆλŠ” μ’Œν‘œμ˜ κ²½λ‘œμˆ˜λŠ” 1
for (let row = 0; row < m; row++) {
numberOfPaths[row][0] = 1;
}

// 3. μ΅œμƒλ‹¨μ— μžˆλŠ” μ’Œν‘œμ˜ κ²½λ‘œμˆ˜λŠ” 1
for (let column = 0; column < n; column++) {
numberOfPaths[0][column] = 1;
}

// 4. κ·Έ μ™Έ 각 μ’Œν‘œλŠ” λ°”λ‘œ μœ„ μ’Œν‘œ(column-1)와 λ°”λ‘œ μ™Όμͺ½ μ’Œν‘œ(row-1)의 경둜수의 ν•©
for (let row = 1; row < m; row++) {
for (let column = 1; column < n; column++) {
numberOfPaths[row][column] =
numberOfPaths[row - 1][column] + numberOfPaths[row][column - 1];
}
}

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

0 comments on commit 07b18e7

Please sign in to comment.