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
29 changes: 29 additions & 0 deletions bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// https://www.acmicpc.net/problem/5639
// 이진 검색트리의 전위 순회 경과가 주어지면, 후위순회 결과 구하기
const filePath =
process.platform === "linux"
? "/dev/stdin"
: require("path").join(__dirname, "input.txt")
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
const log = console.log

const arr = input.map(Number)

const postorder = (root, end) => {
if (root > end) return

let right = end + 1 // 오른쪽 서브트리(루트보다 큰 요소들) 시작점 구하기
for (let i = root + 1; i <= end; i++) {
if (arr[i] > arr[root]) {
right = i
break
}
}

// 후위 순위로 출력
postorder(root + 1, right - 1)
postorder(right, end)
log(arr[root])
}

postorder(0, arr.length - 1)
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// https://www.acmicpc.net/problem/5639
// 이진 검색트리의 전위 순회 경과가 주어지면, 후위순회 결과 구하기

// 핵심: BST의 전위순회 결과가 있기에, 순서대로 트리에 삽입하면 트리가 복원된다
const filePath =
process.platform === "linux"
? "/dev/stdin"
: require("path").join(__dirname, "input.txt")
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
const log = console.log

const arr = input.map(Number)

class Node {
constructor(value) {
this.value = value
this.left = null
this.right = null
}
}

class BinarySearchTree {
constructor() {
this.root = null
}

insert(value) {
if (!this.root) {
this.root = new Node(value)
return
}

let current = this.root
while (true) {
if (value < current.value) {
if (!current.left) {
current.left = new Node(value)
break
}
current = current.left
} else {
if (!current.right) {
current.right = new Node(value)
break
}
current = current.right
}
}
}

postorder(node = this.root) {
if (!node) return

this.postorder(node.left) // 왼쪽 서브트리 순회
this.postorder(node.right) // 오른쪽 서브트리 순회
log(node.value) // 현재 노드 출력
}
}

const tree = new BinarySearchTree()
arr.forEach((item) => tree.insert(item))
tree.postorder()
9 changes: 9 additions & 0 deletions bona1122/[week5]Tree/Binary_search_tree/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
50
30
24
5
28
45
98
52
60
50 changes: 50 additions & 0 deletions bona1122/[week5]Tree/Binary_tree_height/Binary_tree_height.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// https://www.acmicpc.net/problem/1068
const filePath =
process.platform === "linux"
? "/dev/stdin"
: require("path").join(__dirname, "input.txt")
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
const log = console.log

// 노드 제거시, 노드와 노드의 모든 자손이 트리에서 제거됨
// 노드를 지운 후, 트리의 리프노드 개수 구하기
// => 부모노드 정보를 통해 그래프를 구성하고, bfs로 탐색하며 리프노드 개수 카운트

const n = +input[0]
const parents = input[1].split(" ").map(Number)
const remove = +input[2]
const graph = Array.from({ length: n }, () => [])
let root = -1

for (let i = 0; i < n; i++) {
const parent = parents[i]
if (parent === -1) {
root = i
} else {
graph[parent].push(i)
}
}

let result = 0
const queue = remove === root ? [] : [root]
const visited = new Array(n).fill(false)
visited[root] = true

while (queue.length) {
let item = queue.shift()
let isLeaf = true

for (let v of graph[item]) {
if (v !== remove) {
isLeaf = false
if (!visited[v]) {
visited[v] = true
queue.push(v)
}
}
}

if (isLeaf) result++
}

log(result)
3 changes: 3 additions & 0 deletions bona1122/[week5]Tree/Binary_tree_height/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
9
-1 0 0 2 2 4 4 6 6
4
26 changes: 26 additions & 0 deletions bona1122/[week5]Tree/Complete_binary_tree/Complete_binary_tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// https://www.acmicpc.net/problem/9934
const filePath =
process.platform === "linux"
? "/dev/stdin"
: require("path").join(__dirname, "input.txt")
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
const log = console.log

// 상근이는 중위순회로 이진 트리를 순회한 결과를 가지고 있다.
// 각 레벨에 있는 빌딩 번호 구하기
const k = +input[0]
const arr = input[1].split(" ").map(Number)
let result = Array.from({ length: k }, () => [])

const dfs = (arr, depth) => {
if (arr.length < 1) return

const mid = Math.floor(arr.length / 2)
result[depth].push(arr[mid])

dfs(arr.slice(0, mid), depth + 1)
dfs(arr.slice(mid + 1), depth + 1)
}

dfs(arr, 0)
result.forEach((row) => log(row.join(" ")))
2 changes: 2 additions & 0 deletions bona1122/[week5]Tree/Complete_binary_tree/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
3
1 6 4 3 5 2 7
68 changes: 68 additions & 0 deletions bona1122/[week5]Tree/Tree_and_query/Tree_and_query.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// https://www.acmicpc.net/problem/15681
const filePath =
process.platform === "linux"
? "/dev/stdin"
: require("path").join(__dirname, "input.txt")
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
const log = console.log

// 가중치, 방향 없는 트리
// 정점 U를 루트로 하는 서브트리에 속한 정점 수 출력하기

// 방법 1: 문제에서 주어진 힌트 처럼, 자식 배열을 활용
const [N, R, Q] = input[0].split(" ").map(Number)

const graph = Array.from({ length: N + 1 }, () => [])
const query = Array(Q)
const children = Array.from({ length: N + 1 }, () => [])
const size = Array(N + 1).fill(1)

for (let i = 1; i <= N - 1; i++) {
let [u, v] = input[i].split(" ").map(Number)
graph[u].push(v)
graph[v].push(u)
}
let idx = 0
for (let i = N; i < N + Q; i++) {
query[idx++] = +input[i]
}

const makeTree = (cur, parent) => {
for (let next of graph[cur]) {
if (next !== parent) {
children[cur].push(next)
makeTree(next, cur)
}
}
}

// 부모자식관계를 파악하기 위한 두 가지 방법
// 1. 명시적으로 배열에 저장 -> makeTree 선행 필요
const countSubtreeNodes = (cur) => {
for (let next of children[cur]) {
countSubtreeNodes(next)
size[cur] += size[next]
}
}
// 2. visited배열로 부모자식 파악
const visited = Array(N + 1).fill(false)
const countSubtreeNodes2 = (node) => {
if (visited[node]) return size[node]
visited[node] = true // 방문 표시로 부모-자식 관계 파악

for (const next of graph[node]) {
if (!visited[next]) {
// 방문하지 않은 노드는 자식
size[node] += countSubtreeNodes2(next)
}
}
return size[node]
}
/*
makeTree(R, 0)
countSubtreeNodes(R)
log(children)
*/
countSubtreeNodes2(R)

for (let q of query) log(size[q])
12 changes: 12 additions & 0 deletions bona1122/[week5]Tree/Tree_and_query/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
9 5 3
1 3
4 3
5 4
5 6
6 7
2 3
9 6
6 8
5
4
8
36 changes: 36 additions & 0 deletions bona1122/[week5]Tree/Tree_find_parent/Tree_find_parent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// https://www.acmicpc.net/problem/11725

// 루트없는 트리 주어지면(트리루트 1), 2번노드부터 각 노드의 부모를 구하기
// => 그래프 정보 저장하고, bfs로 탐색하면서 부모노드 찾기
const filePath =
process.platform === "linux"
? "/dev/stdin"
: require("path").join(__dirname, "input.txt")
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
const log = console.log

const n = +input[0]
const graph = Array.from({ length: n + 1 }, () => [])
for (let i = 1; i < n; i++) {
let [v1, v2] = input[i].split(" ").map(Number)
graph[v1].push(v2)
graph[v2].push(v1)
}

const visited = new Array(n + 1).fill(false)
const parent = new Array(n + 1).fill(0)

const queue = [1]
visited[1] = true

while (queue.length) {
let item = queue.shift()

for (let v of graph[item]) {
if (visited[v]) continue
visited[v] = true
queue.push(v)
parent[v] = item
}
}
log(result.slice(2).join("\n"))
7 changes: 7 additions & 0 deletions bona1122/[week5]Tree/Tree_find_parent/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
7
1 6
6 3
3 5
4 1
2 4
4 7
40 changes: 40 additions & 0 deletions bona1122/[week5]Tree/Tree_traversal/Tree_traversal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// https://www.acmicpc.net/problem/2263
const filePath =
process.platform === "linux"
? "/dev/stdin"
: require("path").join(__dirname, "input.txt")
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
const log = console.log

// n개의 정점존재, 이진트리의 inorder, postorder 주어지면, preorder 구하기
const n = +input[0]
const inorder = input[1].split(" ").map(Number)
const postorder = input[2].split(" ").map(Number)
let result = ""

// 매번 findIndex하니, 시간초과가 남. => inorder 값의 인덱스를 미리 Map에 저장해두기
const inorderMap = new Map()
inorder.forEach((val, idx) => inorderMap.set(val, idx))

// postorder로 루트 알아내고,
// 그 정보를 통해 inorder에서 왼/오 서브트리 알아내기
// iStart, iEnd: inorder 배열의 범위
// pStart, pEnd: postorder 배열의 범위
const preorder = (iStart, iEnd, pStart, pEnd) => {
if (iStart > iEnd || pStart > pEnd) return

const root = postorder[pEnd]
const rootIdx = inorderMap.get(root)
result += `${root} `

const leftSize = rootIdx - iStart // 왼쪽 서브트리 크기

// 왼쪽 서브트리 처리
preorder(iStart, rootIdx - 1, pStart, pStart + leftSize - 1)

// 오른쪽 서브트리 처리
preorder(rootIdx + 1, iEnd, pStart + leftSize, pEnd - 1)
}

preorder(0, n - 1, 0, n - 1)
log(result.trim())
3 changes: 3 additions & 0 deletions bona1122/[week5]Tree/Tree_traversal/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
3
1 2 3
1 3 2
8 changes: 8 additions & 0 deletions bona1122/[week5]Tree/Tree_traversal_basic/input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
7
A B C
B D .
C E F
E . .
F . G
D . .
G . .
Loading
Loading