diff --git a/longest-palindromic-substring/mmyeon.ts b/longest-palindromic-substring/mmyeon.ts new file mode 100644 index 000000000..cfc3dfe9a --- /dev/null +++ b/longest-palindromic-substring/mmyeon.ts @@ -0,0 +1,35 @@ +/** + * + * 접근 방법 : + * - 팰린드롬은 좌우 대칭 문자열을 찾아야 한다. + * - 문자열 중심이 1개(홀수)일 때와 2개(짝수)일 때 고려해서 팰린드롬을 확장하며 긴 문자열을 리턴한다. + * + * 시간복잡도 : O(n^2) + * - n = s 문자열 길이 + * - 동일 문자인 경우 for문과 while문에서 2번 순회 발생 O(n) + * + * 공간복잡도 : O(1) + * - 고정된 변수만 사용 + * + */ +function longestPalindrome(s: string): string { + let result = ""; + + function expandFromCenter(start: number, end: number) { + while (start >= 0 && end < s.length && s[start] === s[end]) { + start--; + end++; + } + return s.slice(start + 1, end); + } + + for (let i = 0; i < s.length; i++) { + const oddPalindrome = expandFromCenter(i, i); + if (oddPalindrome.length > result.length) result = oddPalindrome; + + const evenPalindrome = expandFromCenter(i, i + 1); + if (evenPalindrome.length > result.length) result = evenPalindrome; + } + + return result; +} diff --git a/rotate-image/mmyeon.ts b/rotate-image/mmyeon.ts new file mode 100644 index 000000000..1dcde104b --- /dev/null +++ b/rotate-image/mmyeon.ts @@ -0,0 +1,29 @@ +/** + Do not return anything, modify matrix in-place instead. + */ + +/** + * + * 접근 방법 : + * - 1. matrix 순회하면서 대각선 기준으로 위쪽만 행과 열 값 바꾼다. + * - 2. 행 기준으로 reverse한다. + * + * 시간복잡도 : O(n^2) + * - n = matrix 행, 열 크기 + * - matrix 순회 O(n^2) + * + * 공간복잡도 : O(1) + * - 추가 배열 사용하지 않음 + * + */ +function rotate(matrix: number[][]): void { + for (let i = 0; i < matrix.length; i++) { + for (let j = i + 1; j < matrix.length; j++) { + [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]]; + } + } + + for (let i = 0; i < matrix.length; i++) { + matrix[i].reverse(); + } +} diff --git a/subtree-of-another-tree/mmyeon.ts b/subtree-of-another-tree/mmyeon.ts new file mode 100644 index 000000000..adc7ec19e --- /dev/null +++ b/subtree-of-another-tree/mmyeon.ts @@ -0,0 +1,61 @@ +class TreeNode { + val: number; + left: TreeNode | null; + right: TreeNode | null; + constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + this.val = val === undefined ? 0 : val; + this.left = left === undefined ? null : left; + this.right = right === undefined ? null : right; + } +} + +/** + * + * 접근 방법 : + * - DFS로 루트 노드를 찾은 뒤, 하위 트리가 동일한 트리인지 확인하기 + * + * 시간복잡도 : O(n * m) + * - n = root 트리 노드의 개수 + * - m = subRoot 트리 노드의 개수 + * - 루트 노드 찾기 위해서 O(n) + * - 동일 트리 체크하기 위해서 O(m) + * + * 공간복잡도 : O(n + m) + * - n = root 트리 높이 + * - m = subRoot 트리 높이 + * - dfs 탐색 최대 깊이 O(n) + * - isSameTree 탐색 최대 깊이 O(m) + * + */ +function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean { + if (!root) return false; + + const isSameTree = ( + node: TreeNode | null, + subNode: TreeNode | null + ): boolean => { + // 두 노드가 null이면 동일한 트리 + if (!node && !subNode) return true; + // 한 노드만 null이면 다른 트리 + if (!node || !subNode) return false; + // 값이 다르면 다른 트리 + if (node.val !== subNode.val) return false; + + // 값이 같으니까 왼쪽, 오른쪽 하위 트리도 비교 + return ( + isSameTree(node.left, subNode.left) && + isSameTree(node.right, subNode.right) + ); + }; + + // 루트 노드 찾기 + const dfs = (node: TreeNode | null): boolean => { + if (!node) return false; + // 동일한 트리인지 확인 + if (isSameTree(node, subRoot)) return true; + // 왼쪽이나 오른쪽 추가 탐색 진행 + return dfs(node.left) || dfs(node.right); + }; + + return dfs(root); +} diff --git a/validate-binary-search-tree/mmyeon.ts b/validate-binary-search-tree/mmyeon.ts new file mode 100644 index 000000000..f66fb1e50 --- /dev/null +++ b/validate-binary-search-tree/mmyeon.ts @@ -0,0 +1,29 @@ +/** + * + * 접근 방법 : + * - 이진 탐색 트리의 특징(왼쪽 자식 노드 < 부모 노드 < 오른쪽 자식 노드)을 이용하여 문제 풀기 + * - 부모 노드 값, 최상위 루트 노드 값을 모두 고려해야 하니까 min, max로 값의 범위 지정하기 + * + * 시간복잡도 : O(n) + * - n = root 트리 노드의 개수 + * - 모든 노드 탐색 : O(n) + * + * 공간복잡도 : O(h) + * - h = root 트리 높이 + * - 재귀 호출이 트리 높이만큼 발생함 + * - 치우친 트리의 경우 h = O(n) + * + */ +function isValidBST(root: TreeNode | null): boolean { + function helper(node: TreeNode | null, min: number, max: number): boolean { + if (!node) return true; + + if (node.val <= min || node.val >= max) return false; + + return ( + helper(node.left, min, node.val) && helper(node.right, node.val, max) + ); + } + + return helper(root, -Infinity, Infinity); +}