Skip to content

Commit 6f4e4dc

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 2c5b297 + a5dbbde commit 6f4e4dc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2347
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Definition for a binary tree node.
2+
class TreeNode {
3+
val: number;
4+
left: TreeNode | null;
5+
right: TreeNode | null;
6+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
7+
this.val = val === undefined ? 0 : val;
8+
this.left = left === undefined ? null : left;
9+
this.right = right === undefined ? null : right;
10+
}
11+
}
12+
13+
// T.C: O(N)
14+
// S.C: O(N^2) - Slice makes n-1, n-2, ..., 1 for n times. So, it's O(N^2).
15+
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
16+
if (preorder.length === 0 || inorder.length === 0) {
17+
return null;
18+
}
19+
const root = new TreeNode(preorder[0]);
20+
const idx = inorder.indexOf(preorder[0]);
21+
root.left = buildTree(preorder.slice(1, idx + 1), inorder.slice(0, idx));
22+
root.right = buildTree(preorder.slice(idx + 1), inorder.slice(idx + 1));
23+
24+
return root;
25+
}
26+
27+
// Not using slice. but I think it's not necessary... first solution is more readable. and that's not so bad.
28+
// T.C: O(N)
29+
// S.C: O(N)
30+
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
31+
// this tree is consist of unique values
32+
const inorderMap = new Map<number, number>();
33+
for (const [i, val] of inorder.entries()) {
34+
inorderMap.set(val, i);
35+
}
36+
37+
function helper(preLeft: number, preRight: number, inLeft: number, inRight: number): TreeNode | null {
38+
if (preLeft > preRight) return null;
39+
40+
const rootValue = preorder[preLeft];
41+
const root = new TreeNode(rootValue);
42+
const inRootIdx = inorderMap.get(rootValue)!;
43+
44+
const leftSize = inRootIdx - inLeft;
45+
46+
root.left = helper(preLeft + 1, preLeft + leftSize, inLeft, inRootIdx - 1);
47+
root.right = helper(preLeft + leftSize + 1, preRight, inRootIdx + 1, inRight);
48+
49+
return root;
50+
}
51+
52+
return helper(0, preorder.length - 1, 0, inorder.length - 1);
53+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution {
2+
private int i, p;
3+
public TreeNode buildTree(int[] preorder, int[] inorder) {
4+
// Time complexity: O(n)
5+
// Space complexity: O(n)
6+
return builder(preorder, inorder, Integer.MIN_VALUE);
7+
}
8+
9+
private TreeNode builder(int[] preorder, int[] inorder, int stop) {
10+
if (p >= preorder.length) return null;
11+
if (inorder[i] == stop) {
12+
i += 1;
13+
return null;
14+
}
15+
16+
TreeNode node = new TreeNode(preorder[p]);
17+
p += 1;
18+
19+
node.left = builder(preorder, inorder, node.val);
20+
node.right = builder(preorder, inorder, stop);
21+
return node;
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Definition for a binary tree node.
2+
# class TreeNode:
3+
# def __init__(self, val=0, left=None, right=None):
4+
# self.val = val
5+
# self.left = left
6+
# self.right = right
7+
class Solution:
8+
# T: O(N)
9+
# S: O(N)
10+
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
11+
# preorder : root - left - right
12+
# inorder : left - root - right
13+
if not preorder and not inorder:
14+
return None
15+
16+
root = TreeNode(preorder[0])
17+
mid = inorder.index(preorder[0])
18+
19+
root.left = self.buildTree(preorder[1 : mid + 1], inorder[:mid])
20+
root.right = self.buildTree(preorder[mid + 1 :], inorder[mid+1:])
21+
22+
return root
23+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* For the number of given nodes N,
3+
*
4+
* Time complexity: O(N)
5+
*
6+
* Space complexity: O(N) at worst
7+
*/
8+
9+
/**
10+
* Definition for a binary tree node.
11+
* struct TreeNode {
12+
* int val;
13+
* TreeNode *left;
14+
* TreeNode *right;
15+
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
16+
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
17+
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
18+
* };
19+
*/
20+
class Solution {
21+
public:
22+
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
23+
unordered_map<int, int> inorder_index_map;
24+
stack<TreeNode*> tree_stack;
25+
26+
for (int i = 0; i < inorder.size(); i++) inorder_index_map[inorder[i]] = i;
27+
28+
TreeNode* root = new TreeNode(preorder[0]);
29+
tree_stack.push(root);
30+
31+
for (int i = 1; i < preorder.size(); i++) {
32+
TreeNode* curr = new TreeNode(preorder[i]);
33+
34+
if (inorder_index_map[curr->val] < inorder_index_map[tree_stack.top()->val]) {
35+
tree_stack.top()->left = curr;
36+
} else {
37+
TreeNode* parent;
38+
while (!tree_stack.empty() && inorder_index_map[curr->val] > inorder_index_map[tree_stack.top()->val]) {
39+
parent = tree_stack.top();
40+
tree_stack.pop();
41+
}
42+
parent->right = curr;
43+
}
44+
tree_stack.push(curr);
45+
}
46+
47+
return root;
48+
}
49+
};
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
/**
3+
* * 문제에서 정의된 타입
4+
*/
5+
export class TreeNode {
6+
val: number
7+
left: TreeNode | null
8+
right: TreeNode | null
9+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
10+
this.val = (val === undefined ? 0 : val)
11+
this.left = (left === undefined ? null : left)
12+
this.right = (right === undefined ? null : right)
13+
}
14+
}
15+
16+
/**
17+
* ! 문제에서의 Output과 실제 정의된, 사용되는 output이 다르기 때문에, 한 번 변환 작업을 거처야함. (실제 제출 시 제외한 함수 입니다.)
18+
*/
19+
// function treeToArray(root: TreeNode | null): (number | null)[] {
20+
// if (!root) return [];
21+
// const result: (number | null)[] = [];
22+
// const queue: (TreeNode | null)[] = [root];
23+
// while (queue.length > 0) {
24+
// const node = queue.shift();
25+
// if (node) {
26+
// result.push(node.val);
27+
// queue.push(node.left);
28+
// queue.push(node.right);
29+
// } else {
30+
// result.push(null);
31+
// }
32+
// }
33+
// while (result[result.length - 1] === null) result.pop();
34+
// return result;
35+
// }
36+
37+
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
38+
if (preorder.length === 0 || inorder.length === 0) return null;
39+
40+
const rootVal = preorder[0];
41+
const inorderIndex = inorder.indexOf(rootVal);
42+
const leftInorder = inorder.slice(0, inorderIndex);
43+
44+
return new TreeNode(
45+
rootVal,
46+
buildTree(
47+
preorder.slice(1, 1 + leftInorder.length),
48+
leftInorder
49+
),
50+
buildTree(
51+
preorder.slice(1 + leftInorder.length),
52+
inorder.slice(inorderIndex + 1)
53+
),
54+
);
55+
}
56+
57+
58+
// const preorder = [3, 9, 20, 15, 7];
59+
// const inorder = [9, 3, 15, 20, 7];
60+
// console.log('output:', treeToArray(buildTree(preorder, inorder)));
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""TC: O(n), SC: O(n)
2+
3+
아이디어:
4+
- preorder 트리가 주어져 있다면 다음과 같이 분할할 수 있다.
5+
- [root값, [...left], [...right]]
6+
- 위의 left, right는 preorder 트리와 같은 방식으로 구성된다.
7+
- inorder 트리가 주어져 있다면 다음과 같이 분할할 수 있다.
8+
- [[...left], root값, [...right]]
9+
- 위의 left, right는 inorder 트리와 같은 방식으로 구성된다.
10+
- 이때,
11+
- left의 첫 아이템이 인덱스 inorder_s에 있고,
12+
- right의 마지막 아이템이 인덱스 inorder_e - 1에 있다고 하자.
13+
- 즉, inorder_e를 미포함!
14+
- preorder 트리의 맨 앞 값을 통해 root값 val을 찾고, 이 값으로 inorder의 root값의 인덱스를 찾을 수 있다.
15+
- 모든 node의 val값이 unique한 것이 조건으로 주어져 있으므로 val값의 indices를 전처리해둘 수 있다.
16+
- 이때, inorder의 root값의 인덱스를 inorder_root이라고 하자.
17+
- inorder의 root값의 위치와 inorder 트리의 시작 위치를 알 수 있다면
18+
[...left]의 길이 left_len을 알 수 있다.
19+
- left_len = inorder_root - inorder_start
20+
- preorder 트리의 left의 루트는 [...left]의 첫 아이템, 즉, preorder_root에 1을 더한 값이다.
21+
- preorder 트리의 right의 루트는 [...right]의 첫 아이템, 즉, preorder_root + 1 + left_len이다.
22+
- root값을 구할 수 없으면 노드가 없다.
23+
- inorder_s >= inorder_e와 같이 판별이 가능하다. 즉, 아이템이 하나도 없는 경우.
24+
25+
위의 아이디어를 종합하면,
26+
- preorder 트리의 루트 인덱스 preorder_root가 주어진, 구간 (inorder_s, inorder_e)에서 정의된 inorder 트리는
27+
- val값은 preorder[preorder_root]이 된다.
28+
- left node는 아래와 같이 구해진다.
29+
- preorder 트리의 루트 인덱스 preorder_root + 1,
30+
- 구간 (inorder_s, inorder_root)
31+
- 이때 구간이 유효하지 않으면 노드가 없다.
32+
- right node는 아래와 같이 구해진다.
33+
- preorder 트리의 루트 인덱스 preorder_root + 1 + left_len,
34+
- 구간 (inorder_root + 1, inorder_end)
35+
- 이때 구간이 유효하지 않으면 노드가 없다.
36+
37+
38+
SC:
39+
- 처음 inorder_indices를 계산할때 O(n).
40+
- 아래의 build함수 호출이 최대 트리의 깊이만큼 재귀를 돌면서 쌓일 수 있다.
41+
- 트리의 깊이는 최악의 경우 O(n).
42+
43+
TC:
44+
- build함수는 O(1). 코드 참조.
45+
- 위의 과정을 n개의 노드에 대해 반복하므로 O(n).
46+
"""
47+
48+
49+
# Definition for a binary tree node.
50+
# class TreeNode:
51+
# def __init__(self, val=0, left=None, right=None):
52+
# self.val = val
53+
# self.left = left
54+
# self.right = right
55+
class Solution:
56+
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
57+
inorder_indices = {v: i for i, v in enumerate(inorder)}
58+
59+
def build(inorder_s, inorder_e, preorder_root):
60+
if inorder_s >= inorder_e: # O(1)
61+
return None
62+
val = preorder[preorder_root] # O(1)
63+
inorder_root = inorder_indices[val] # O(1)
64+
left_len = inorder_root - inorder_s # O(1)
65+
return TreeNode(
66+
val,
67+
left=build(inorder_s, inorder_root, preorder_root + 1),
68+
right=build(inorder_root + 1, inorder_e, preorder_root + 1 + left_len),
69+
)
70+
71+
return build(0, len(inorder), 0)
72+
73+
74+
"""
75+
그런데 위의 아이디어를 다시 생각해보면, 모든 노드들을 preorder 순서로 순회한다!
76+
- `val = preorder[preorder_root]`와 같은 방식으로 val값을 구하지 않고, 주어진 preorder를 순서대로 가져와도 됨.
77+
- 즉, preorder를 iterator로 바꿔서 next를 통해 값을 하나씩 뽑아와서 건네줘도 된다.
78+
- 이렇게 하면 build함수에 preorder_root를 전달하지 않아도 됨.
79+
"""
80+
81+
82+
class Solution:
83+
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
84+
inorder_indices = {v: i for i, v in enumerate(inorder)}
85+
preorder_iter = iter(preorder)
86+
87+
def build(inorder_s, inorder_e):
88+
if inorder_s >= inorder_e: # O(1)
89+
return None
90+
val = next(preorder_iter) # O(1)
91+
inorder_root = inorder_indices[val] # O(1)
92+
return TreeNode(
93+
val,
94+
left=build(inorder_s, inorder_root),
95+
right=build(inorder_root + 1, inorder_e),
96+
)
97+
98+
return build(0, len(inorder))
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
function TreeNode(val, left, right) {
2+
this.val = val === undefined ? 0 : val;
3+
this.left = left === undefined ? null : left;
4+
this.right = right === undefined ? null : right;
5+
}
6+
7+
const buildTree = function (preorder, inorder) {
8+
if (preorder.length === 0) return null;
9+
10+
const rootNode = new TreeNode(preorder[0]);
11+
const rootValueIndexAtInorder = inorder.indexOf(preorder[0]);
12+
13+
const leftLength = rootValueIndexAtInorder - 0;
14+
const rightLength = inorder.length - 1 - rootValueIndexAtInorder;
15+
16+
const leftPreorder = preorder.slice(1, 1 + leftLength);
17+
const leftInorder = inorder.slice(0, 0 + leftLength);
18+
rootNode.left = buildTree(leftPreorder, leftInorder);
19+
20+
const rightPreorder = preorder.slice(
21+
1 + leftLength,
22+
1 + leftLength + rightLength
23+
);
24+
const rightInorder = inorder.slice(
25+
rootValueIndexAtInorder + 1,
26+
rootValueIndexAtInorder + 1 + rightLength
27+
);
28+
rootNode.right = buildTree(rightPreorder, rightInorder);
29+
30+
return rootNode;
31+
};
32+
33+
function bfsTraversal(root) {
34+
const treeValues = [];
35+
36+
const queue = [];
37+
queue.push(root);
38+
39+
while (queue.length > 0) {
40+
const n = queue.length;
41+
42+
for (let i = 0; i < n; i++) {
43+
const currentNode = queue.shift();
44+
45+
if (currentNode) {
46+
treeValues.push(currentNode.val);
47+
queue.push(currentNode.left);
48+
queue.push(currentNode.right);
49+
} else {
50+
treeValues.push(null);
51+
queue.push(null);
52+
queue.push(null);
53+
}
54+
}
55+
56+
if (queue.every((el) => el === null)) break;
57+
}
58+
59+
return treeValues;
60+
}
61+
62+
// console.log(bfsTraversal(buildTree([3, 9, 20, 15, 7], [9, 3, 15, 20, 7])));
63+
console.log(bfsTraversal(buildTree([1, 2], [2, 1])));

0 commit comments

Comments
 (0)