Skip to content
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
59 changes: 59 additions & 0 deletions longest-substring-without-repeating-characters/Blossssom.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

저와 똑같이 dvdf에서 한 번 쓴 맛을 보신 것 같아 웃음이 났습니다ㅋㅋㅋ 풀이 1에서 map으로 정리해주신 것에서, 풀이 2의 해당 인덱스로 점프하는 과정으로 수정해 주셨는데, 훨씬 더 효율적이겠죠. 숫자 방면의 직관이 잘 드러난 케이스로 생각합니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* @param s - 문자열 입력값
* @returns - 부분 문자열 중복없이 가장 긴 문자열의 길이
* @description
* - 풀이 1: 앞단계를 Map으로 정리 후 같은 값이 있을 경우 해당 값을 삭제할 때 까지 반복
* - 삭제 전 길이를 누적해 가장 큰 값을 반환
*
* - 풀이 2: 반복을 돌며 찾는게 아닌 해당 idx로 점프하는 과정으로 변경
* - 최악의 경우를 이전 풀이 1보다 개선
*/

// function lengthOfLongestSubstring(s: string): number {
// const saveMap: Map<string, boolean> = new Map();
// const arr = [];
// for (let i = 0; i < s.length; i++) {
// if (saveMap.has(s[i])) {
// for (const key of saveMap.keys()) {
// arr.push(saveMap.size);
// saveMap.delete(key);
// if (key === s[i]) {
// break;
// }
// }
// }
// saveMap.set(s[i], true);
// }

// arr.push(saveMap.size);

// return Math.max(...arr);
// }

function lengthOfLongestSubstring(s: string): number {
const map = new Map<string, number>();

let maxLength = 0;
let start = 0;

for (let i = 0; i < s.length; i++) {
const char = s[i];
// 해당 문자열이 있고, 그 값이 start 보다 크거나 같을 경우
// start를 중복 문자 바로 다음 칸으로 이동
if (map.has(char) && map.get(char)! >= start) {
start = map.get(char)! + 1;
}

map.set(char, i);

// 현재 idx - 시작점 + 1 === 누적 문자열의 길이
maxLength = Math.max(maxLength, i - start + 1);
}

return maxLength;
}

const s = "dvdf";
lengthOfLongestSubstring(s);


59 changes: 59 additions & 0 deletions number-of-islands/Blossssom.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

얼음의 갯수 등의 로컬라이징도 많이 되었던 문제죠! 저도 dfs로 접근했습니다만, nested function을 싫어하는 취향에 더해 dfs를 위해 반환값이 있는 함수를 짜는 것이 너무 불편하더라고요. 그래서 Swift의 inout 기능을 사용해서 풀었습니다.
제시해주신 nested function도 물론 좋은 풀이방법이라고 생각합니다! 언어별로 가지는 변수의 스코프, 그리고 예외적인 사항에서 어느 지점의 변수를 참조하는지 잘 파악해 두는 것이 중요하다 생각하게 됩니다. ts에서는 탐색 함수를 분리하면 어떤 모양일지 궁금하네요.

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* @param grid - 섬(1), 물(0)로 이뤄진 m * n 2차원 배열
* @returns - 섬의 갯수 (연결되지 않으면 개별 섬)
* @description
* - dfs 까진 알았는데 AI의 도움을 받았음
* - 탐색 문제에서 디테일까지 접근하는 연습이 필요
* - 시간 복잡도 O(M * N)
*/

function numIslands(grid: string[][]): number {
const visit = Array.from({ length: grid.length }, () =>
Array.from({ length: grid[0].length }, () => false)
);

const moveY = [0, 0, -1, 1];
const moveX = [-1, 1, 0, 0];

let cnt = 0;
function dfs(y: number, x: number) {
visit[y][x] = true;
// 4 방향 index 확인
for (let i = 0; i < 4; i++) {
const nextY = y + moveY[i];
const nextX = x + moveX[i];

if (
nextX >= 0 &&
nextY >= 0 &&
nextX < grid[0].length &&
nextY < grid.length &&
grid[nextY][nextX] === "1" &&
!visit[nextY][nextX]
) {
dfs(nextY, nextX);
}
}
}

for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
if (grid[i][j] === "1" && !visit[i][j]) {
cnt++;
dfs(i, j);
}
}
}

return cnt;
}

const grid = [
["1", "1", "0", "0", "0"],
["1", "1", "0", "0", "0"],
["0", "0", "1", "0", "0"],
["0", "0", "0", "1", "1"],
];
numIslands(grid);


71 changes: 71 additions & 0 deletions reverse-linked-list/Blossssom.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

참조를 즉석에서 바꿔 주신 것도 좋네요! LeetCode의 리스트 문제는 항상 참조를 컨트롤하는 게 고역인 듯 합니다. console.log를 지우셨다면 시간 효율성은 더 잘 나오셨을 것 같네요!!

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
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;
}
}

/**
*
* @param head - ListNode 구조체
* @returns - 역순 head
* @description
* - 1차 시도: 단순 val 추출 후 역순으로 재 배치
* - 2차 시도: head를 순회하며 스와핑, prev에 재 배치 하며 진행
*/

// function reverseList(head: ListNode | null): ListNode | null {
// if (!head) {
// return head;
// }

// let currentNode: ListNode | null = head;
// let reversed: ListNode = new ListNode();
// const saveArr = [];
// while (currentNode?.val !== undefined) {
// saveArr.push(currentNode.val);
// currentNode = currentNode.next;
// }

// let check = reversed;
// for (let i = saveArr.length; i > 0; i--) {
// check.val = saveArr[i - 1];
// if (i - 1) {
// check.next = new ListNode();
// check = check.next;
// }
// }

// return reversed;
// }

function reverseList(head: ListNode | null): ListNode | null {
if (!head) {
return null;
}

let prevNode: ListNode | null = null;
let nextNode: ListNode | null = null;

console.log(head);
while (head) {
nextNode = head.next;
head.next = prevNode;
prevNode = head;
head = nextNode;
console.log(head, nextNode, prevNode);
}

return prevNode;
}

const head = new ListNode(
0,
new ListNode(1, new ListNode(4, new ListNode(-2)))
);

reverseList(head);


86 changes: 86 additions & 0 deletions set-matrix-zeroes/Blossssom.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

추가 공간을 쓰지 않게끔 풀이를 진행하는 것이 어려웠던 문제였습니다. 전반적으로 첫 번째 요소와 탐색 측면에서 힘을 주신 부분이 보이네요.

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* @param matrix - 2중 배열 그리드
* @description
* - 요소가 0일 경우 속한 행과 열 전체를 0으로 변경
*
* - 풀이 1. 단순하게 0 목록을 만들어 해당 요소의 행과 열을 변경
* - 풀이 2. 풀이 1은 매번 덮어씌우기를 진행하므로 행과 열 마다 첫번 째 요소를 메모장으로 사용.
* - 내부를 탐색하며 진행
*/

// function setZeroes(matrix: number[][]): void {
// const zeroes = [];

// for (let i = 0; i < matrix.length; i++) {
// for (let j = 0; j < matrix[0].length; j++) {
// if (matrix[i][j] === 0) {
// zeroes.push([i, j]);
// }
// }
// }

// for (let i = 0; i < zeroes.length; i++) {
// const [row, col] = zeroes[i];
// console.log(row, col);

// matrix[row] = Array.from({ length: matrix[row].length }, () => 0);
// console.log(matrix);

// for (let j = 0; j < matrix.length; j++) {
// matrix[j][col] = 0;
// }
// }
// }

function setZeroes(matrix: number[][]): void {
const m = matrix.length;
const n = matrix[0].length;
let isFirstRowZero = false;
let isFirstColZero = false;

for (let i = 0; i < m; i++) {
if (!matrix[i][0]) {
isFirstColZero = true;
}
}

for (let j = 0; j < n; j++) {
if (!matrix[0][j]) {
isFirstRowZero = true;
}
}

for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
if (!matrix[i][j]) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}

for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
if (matrix[i][0] === 0 || matrix[0][j] === 0) {
matrix[i][j] = 0;
}
}
}

if (isFirstColZero) {
for (let i = 0; i < m; i++) matrix[i][0] = 0;
}
if (isFirstRowZero) {
for (let j = 0; j < n; j++) matrix[0][j] = 0;
}
}

const matrix = [
[1, 1, 1],
[1, 0, 1],
[1, 1, 1],
];

setZeroes(matrix);


46 changes: 46 additions & 0 deletions unique-paths/Blossssom.ts
Copy link
Contributor

Choose a reason for hiding this comment

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

DP 문제 측면에서 이 문제가 파스칼의 삼각형과 동치라고 하네요! 처음에 저는 배열을 초기화하고 모든 경로를 큐에 넣어서 bfs로 풀고자 했던 기억이 납니다. 한편 수학 공식 단 한 줄로 끝낼 수도 있어서 이건 조금 허탈했어요.

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @param m - grid row length
* @param n - grid col length
* @returns - 오른쪽 아래 모서리에 도착할 수 있는 경로의 수
* @description
* - [0, 0] 시작
* - 아래쪽 혹은 오른쪽으로만 이동 가능
* - dfs인줄 알았는데 visit도 필요 없고 결국 dp.
*
* - 풀이 1. 각 지점에 도달할 수 있는 경우는 이전 idx의 경우의 수들 (x - 1, y - 1)의 합이다.
* - 따라서 이전 idx의 값들을 누적해가며 가장 마지막인 도착점의 누적 값이 결과.
*
* - 풀이 2. 풀이 1과 방식은 같지만 1차원 배열을 덮어 씌워가며 공간 복잡도를 줄임
*/

// function uniquePaths(m: number, n: number): number {
// const dp = Array.from({ length: m }, () =>
// Array.from({ length: n }, () => 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];
// console.log(dp);
// }
// }

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

function uniquePaths(m: number, n: number): number {
const dp = Array.from({ length: n }, () => 1);

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

const m = 3;
const n = 7;
uniquePaths(m, n);