Skip to content

[gomgom22] Week15 #1119

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

Merged
merged 4 commits into from
Mar 22, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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)
// }
// }

/**
* 전위 순회(preorder)와 중위 순회(inorder) 배열을 이용해 이진 트리를 재구성하는 함수.
*
* @param {number[]} preorder - 트리의 전위 순회 배열 (루트 → 왼쪽 → 오른쪽 순서).
* @param {number[]} inorder - 트리의 중위 순회 배열 (왼쪽 → 루트 → 오른쪽 순서).
* @returns {TreeNode | null} - 재구성된 이진 트리의 루트 노드, 만약 트리가 비어있다면 null.
*
* 시간 복잡도: O(n)
* - 각 노드를 한 번씩 처리함.
*
* 공간 복잡도: O(n)
* - 재귀 호출 스택과 중위 순회 값-인덱스 해시맵 저장 공간 포함.
*/
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
// 중위 순회 배열의 각 값과 해당 인덱스를 저장
const inorderIndexMap = new Map<number, number>();
inorder.forEach((value, index) => inorderIndexMap.set(value, index));

// 처리할 노드의 인덱스를 추적
let preorderIndex = 0;

// 재귀적으로 서브트리를 재구성하는 함수
const helper = (left: number, right: number): TreeNode | null => {
// 현재 서브트리의 범위가 유효하지 않은 경우
if (left > right) return null;

// 전위 순회 배열에서 현재 노드 값을 가져와 루트로 사용하고 인덱스 증가
const rootVal = preorder[preorderIndex++];
// 새로운 TreeNode 객체 생성
const root = new TreeNode(rootVal);

// 해시맵에서 현재 루트 값의 인덱스를 찾아 중위 순회 배열 내에서의 위치 확인
const rootIndex = inorderIndexMap.get(rootVal)!;

// 중위 순회 배열에서 왼쪽 서브트리 범위 (left ~ rootIndex - 1)를 재귀 호출로 구성
root.left = helper(left, rootIndex - 1);
// 중위 순회 배열에서 오른쪽 서브트리 범위 (rootIndex + 1 ~ right)를 재귀 호출로 구성
root.right = helper(rootIndex + 1, right);

// 현재 서브트리의 루트 노드를 반환
return root;
};

// 전체 트리를 재구성하기 위해 중위 순회 배열의 전체 범위(0 ~ inorder.length - 1)를 헬퍼 함수에 전달
return helper(0, inorder.length - 1);
}

27 changes: 27 additions & 0 deletions rotate-image/Yjason-K.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* 주어진 정사각형 행렬을 90도 회전시키는 함수
*
* @param {number[][]} matrix - 2차원 배열로 표현된 정사각형 행렬.
*
* 시간 복잡도: O(n^2)
* - n * n 행렬, 모든 요소를 한 번씩 방문.
*
* 공간 복잡도: O(1)
* - 추가적인 공간 사용 X
*/
function rotate(matrix: number[][]): void {
// 행렬의 크기 n (정사각형 행렬이므로 행과 열의 수는 동일)
const n = matrix.length;

// 행렬의 대각선을 기준으로 좌표 (i, j)와 (j, i)의 요소를 교환.
for (let i = 0; i < n; i++) {
// j는 i부터 시작하여 중복 교환을 방지
for (let j = i; j < n; j++) {
// 배열 구조 분해 할당을 이용하여 두 요소를 스왑
[matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
}
// 각 행을 반전
matrix[i].reverse();
}
}

51 changes: 51 additions & 0 deletions subtree-of-another-tree/Yjason-K.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Definition for a binary tree node.
* 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)
* }
* }
*/


/**
* subTree가 root의 포함되는지 확인하는 함수
*
* @param {TreeNode | null} root - 주어진 트리
* @param {TreeNode | null} subRoot - 포함되는지 확인할 트리
* @returns {boolean} - subRoot가 root에 포함되는지 여부
*
* 시간 복잡도: O(n * m)
* - `isSameTree`는 두 트리가 동일한지 확인하는데 O(m) 시간이 걸림 (`m`: subRoot의 노드 수).
* - `isSubtree`는 `root`의 각 노드에서 `isSameTree`를 호출할 수 있음 (`n`: root의 노드 수).
* - 따라서 최악의 경우 O(n * m).
*
* 공간 복잡도: O(n)
* - 재귀 호출에 따른 call stack 사용
*/
function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean {
if (!subRoot) return true;
if (!root) return false;

const isSameTree = (treeA: TreeNode | null, treeB: TreeNode | null ): boolean => {
// 두 트리 모두 null 인 경우 true
if (!treeA && !treeB) return true;
// 하나만 null 인 경우 false
if (!treeA || !treeB) return false;
// val이 다른 경우 false
if (treeA.val !== treeB.val) return false;
return isSameTree(treeA.left, treeB.left) && isSameTree(treeA.right, treeB.right)
}

// 현재 노드에서 subRoot가 시작되는 트리인지 확인
if (isSameTree(root, subRoot)) return true;

// 왼쪽, 오른쪽 하위 트에 subRoot가 포함되는지 확인
return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot)
};