Skip to content

Commit 522b40d

Browse files
committed
kth smallest element in a bst solution
1 parent ce20053 commit 522b40d

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Definition for a binary tree node.
2+
public class TreeNode {
3+
public var val: Int
4+
public var left: TreeNode?
5+
public var right: TreeNode?
6+
public init() { self.val = 0; self.left = nil; self.right = nil; }
7+
public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
8+
public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
9+
self.val = val
10+
self.left = left
11+
self.right = right
12+
}
13+
}
14+
15+
class Solution {
16+
// ์ž์ฒด ํ’€์ด - heapq๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ๊ทธ์— ๋”ฐ๋ผ ํŠธ๋ฆฌ์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ ๊บผ๋‚ด์„œ ๋„ฃ์€ ๋‹ค์Œ, k์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๋ฝ‘์•„๋‚ด๋Š” ๋ฐฉ์‹
17+
// ๋ชจ๋“  ์ข…๋ฅ˜์˜ ์ด์ง„ ํŠธ๋ฆฌ์— ์ ์šฉ ๊ฐ€๋Šฅ
18+
func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int {
19+
var heapq = HeapQ<Int>(criteria: <)
20+
extractElement(root, &heapq)
21+
22+
var result: Int? = nil
23+
24+
for _ in 0..<k {
25+
result = heapq.pop()
26+
}
27+
28+
return result ?? 0
29+
}
30+
31+
func extractElement(_ root: TreeNode?, _ heapq: inout HeapQ<Int>) {
32+
guard let root else { return }
33+
34+
heapq.push(root.val)
35+
36+
extractElement(root.left, &heapq)
37+
extractElement(root.right, &heapq)
38+
}
39+
}
40+
41+
struct HeapQ<Element> {
42+
var storage: [Element]
43+
var criteria: (Element, Element) -> Bool
44+
45+
var isEmpty: Bool {
46+
storage.isEmpty
47+
}
48+
49+
init(
50+
storage: [Element] = [],
51+
criteria: @escaping (Element, Element) -> Bool
52+
) {
53+
self.storage = storage
54+
self.criteria = criteria
55+
}
56+
57+
mutating func push(_ element: Element) {
58+
storage.append(element)
59+
siftUp(from: storage.endIndex - 1)
60+
}
61+
62+
mutating func pop() -> Element? {
63+
guard !isEmpty else { return nil }
64+
65+
storage.swapAt(0, storage.endIndex - 1)
66+
67+
defer {
68+
if !isEmpty {
69+
siftDown(from: 0)
70+
}
71+
}
72+
73+
return storage.removeLast()
74+
}
75+
76+
private mutating func siftUp(from index: Int) {
77+
var parent = (index - 1) / 2
78+
var child = index
79+
80+
while child > 0 && criteria(storage[child], storage[parent]) {
81+
storage.swapAt(parent, child)
82+
child = parent
83+
parent = (child - 1) / 2
84+
}
85+
}
86+
87+
private mutating func siftDown(from index: Int) {
88+
var parent = index
89+
90+
while true {
91+
let left = 2 * parent + 1
92+
let right = 2 * parent + 2
93+
var candidate = parent
94+
95+
if left < storage.count && criteria(storage[left], storage[candidate]) {
96+
candidate = left
97+
}
98+
99+
if right < storage.count && criteria(storage[right], storage[candidate]) {
100+
candidate = right
101+
}
102+
103+
if candidate == parent { return }
104+
105+
storage.swapAt(parent, candidate)
106+
parent = candidate
107+
}
108+
}
109+
110+
// AI์™€ ๋…ผ์˜ํ•œ ํ’€์ด: BST์˜ ์„ฑ์งˆ์„ ์ด์šฉํ•ด ์ค‘์œ„ ํƒ์ƒ‰์„ ์ˆ˜ํ–‰
111+
// ์›์†Œ๋ฅผ ์ผ๋ฐ˜ ๋ฐฐ์—ด์— ์‚ฝ์ž…ํ•จ์œผ๋กœ์จ, ์‚ฝ์ž…์‹œ๋งˆ๋‹ค O(logN)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ–์ง€ ์•Š๊ณ  O(1)์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ€์ง
112+
// ์ค‘์œ„ ํƒ์ƒ‰: ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ - ์ž๊ธฐ ์ž์‹  - ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ ์ˆœ์œผ๋กœ ํƒ์ƒ‰
113+
func kthSmallest2(_ root: TreeNode?, _ k: Int) -> Int {
114+
var values: [Int] = []
115+
traverse(root, &values, k)
116+
117+
return values[k - 1]
118+
}
119+
120+
func traverse(_ node: TreeNode?, _ values: inout [Int], _ threshold: Int) {
121+
guard let node, values.count < threshold else { return }
122+
traverse(node.left, &values, threshold)
123+
124+
guard values.count < threshold else { return }
125+
values.append(node.val)
126+
127+
traverse(node.right, &values, threshold)
128+
}
129+
}

0 commit comments

Comments
ย (0)