diff --git a/longest-substring-without-repeating-characters/Yjason-K.ts b/longest-substring-without-repeating-characters/Yjason-K.ts new file mode 100644 index 000000000..689bc03e1 --- /dev/null +++ b/longest-substring-without-repeating-characters/Yjason-K.ts @@ -0,0 +1,40 @@ +/** + * 주어진 문자열에서 반복되지 않는 가장 긴 부분 문자열의 길이를 반환. + * @param {sting} s - 주어진 문자열 + * @returns {number} 주어진 문자열에서 중복 문자가 없는 가장 긴 부분 문자열의 길이 + * + * 시간 복잡도: O(n) + * - 문자열 1회 순회 + * + * 공간 복잡도: O(n) + * - 최대 문자열의 모든 문자를 Map에 저장하므로 입력 문자열의 길이에 비례하는 공간을 사용 + */ +function lengthOfLongestSubstring(s: string): number { + // 각 문자의 idx를 보관할 Map + const charMap: Map = new Map(); + + // substring 최대 길이 + let maxLen = 0; + // substring 시작점 + let start = 0; + + for (let end = 0; end < s.length; end++) { + const char = s[end]; + + // 문자가 이전에 등장했으며, 윈도우의 시작점(start)보다 크거나 같을 경우 업데이트 + const prevIdx = charMap.get(char); + if (prevIdx && prevIdx >= start) { + start = prevIdx + 1; // 중복 문자 이후로 윈도우의 시작점 이동 + } + + // 현재 문자의 위치 업데이트 + charMap.set(char, end); + + // 최대 길이 갱신 + maxLen = Math.max(maxLen, end - start + 1); + + } + + return maxLen; +} + diff --git a/number-of-islands/Yjason-K.ts b/number-of-islands/Yjason-K.ts new file mode 100644 index 000000000..1812e0dc7 --- /dev/null +++ b/number-of-islands/Yjason-K.ts @@ -0,0 +1,65 @@ +/** + * 2차원 배열을 돌며 상하좌우로 이동할 수 연속하여 이동할 수 있는 공간(섬) 찾기 + * @param {sting[][]} grid - 2차원 배열 + * @returns {number} 만들 수 있는 공간(섬)의 갯수 + * + * 시간 복잡도: O(n * m) + * m == grid.length + * n == grid[i].length + * + * 공간 복잡도: O(n * m) + * m == grid.length + * n == grid[i].length + */ +function numIslands(grid: string[][]): number { + // 방문 배열 생성 + const visited: boolean[][] = Array.from( + { length: grid.length }, + () => Array(grid[0].length).fill(false) + ); + + let islands = 0; + + const bfs = (i: number, j: number): void => { + // 방문 처리 + visited[i][j] = true; + + // 상, 하, 좌, 우 + const directions: [number, number][] = [ + [-1, 0], + [1, 0], + [0, -1], + [0, 1], + ]; + + for (const direction of directions) { + const nextI = i + direction[0]; + const nextJ = j + direction[1]; + if ( + nextI >= 0 && + nextI < grid.length && + nextJ >= 0 && + nextJ < grid[0].length && + !visited[nextI][nextJ] && + grid[nextI][nextJ] === '1' + ) { + bfs(nextI, nextJ); + } + } + }; + + for (let i = 0; i < grid.length; i++) { + for (let j = 0; j < grid[0].length; j++) { + if (grid[i][j] === '1' && !visited[i][j]) { + // 새로운 섬 발견 + islands++; + + // BFS 실행 + bfs(i, j); + } + } + } + + return islands; +} + diff --git a/reverse-linked-list/Yjason-K.ts b/reverse-linked-list/Yjason-K.ts new file mode 100644 index 000000000..4f80d1f65 --- /dev/null +++ b/reverse-linked-list/Yjason-K.ts @@ -0,0 +1,37 @@ +/** + * 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) + * } + * } + */ + +/** + * linked list 를 뒤집는 함수. + * + * @param {ListNode | null} head - linked list 의 시작 노드 + * @returns {ListNode | null} 뒤집힌 단일 연결 리스트의 시작 노드 + * + * - 시간 복잡도(Time Complexity): O(n) + * - llinked list 길이 만큼 순회 + * + * - 공간 복잡도(Space Complexity): O(1) + */ +function reverseList(head: ListNode | null): ListNode | null { + let prev: ListNode | null = null; + let curr: ListNode | null = head; + + while (curr !== null) { + const next: ListNode | null = curr.next; // 다음 노드를 잠시 저장 + curr.next = prev; // 현재 노드의 next를 이전 노드를 가리키도록 변경 + prev = curr; // prev를 현재 노드로 업데이트 + curr = next; // curr를 다음 노드로 이동 + } + + return prev; // prev가 뒤집힌 연결 리스트의 시작 노드가 됩니다. +}; + diff --git a/set-matrix-zeroes/Yjason-K.ts b/set-matrix-zeroes/Yjason-K.ts new file mode 100644 index 000000000..19dc6e728 --- /dev/null +++ b/set-matrix-zeroes/Yjason-K.ts @@ -0,0 +1,38 @@ +/** + * 2차원 배열을 돌며 0을 적용해야하는 row와 col을 조회 후 다시 2차원 배열을 돌며 0으로 변환 + * @param {number[][]} matrix - 2차원 배열 + * @return + * + * - 시간 복잡도: O(m * n) + * - m x n 크기의 배열을 2번 순회 + * + * - 공간 복잡도: O(m + n) + * - 최대 m(행) + n(열) 크기의 Set을 사용 + */ +function setZeroes(matrix) { + const m = matrix.length; + const n = matrix[0].length; + + const rowZeroSet = new Set(); + const colZeroSet = new Set(); + + // 배열을 돌며 0으로 바꿔야 할 행과 열을 기록 + for (let i=0; i < m; i ++) { + for (let j=0; j < n; j++) { + if (matrix[i][j] === 0) { + rowZeroSet.add(i); + colZeroSet.add(j); + } + } + } + + // 0으로 변경해야 하는 행과 열을 변환 + for (let i=0; i < m; i ++) { + for (let j=0; j < n; j++) { + if (rowZeroSet.has(i) || colZeroSet.has(j)) { + matrix[i][j] = 0; + } + } + } +} + diff --git a/unique-paths/Yjason-K.ts b/unique-paths/Yjason-K.ts new file mode 100644 index 000000000..32c494b77 --- /dev/null +++ b/unique-paths/Yjason-K.ts @@ -0,0 +1,29 @@ + +/** + * m * n 그리드에서 좌측 상단에서 우측 하단까지 갈 수 있는 경로의 수 + * @param {number} m - 그리드의 행 길이 + * @param {number} n - 그리드의 열 길이 + * @returns {number} 우측 하단까지 갈 수 있는 경우의 수 + * + * - 시간 복잡도: O(m * n) + * - 전체 셀을 한 번씩 순회 + * + * - 공간 복잡도: O(n) + * - 1차원 배열 사용 (열 크기만큼의 배열) + */ +function uniquePaths(m: number, n: number): number { + // n(열) 크기의 배열을 생성 + const dp = Array(n).fill(1); + + + for (let i = 1; i < m; i++) { + for (let j = 1; j < n; j++) { + // 현재 값 = 위쪽(dp[j]) + 왼쪽(dp[j-1]) + dp[j] = dp[j] + dp[j - 1]; + } + } + + // dp[n-1]에 우측 하단까지의 경로 수가 저장 + return dp[n - 1]; +} +