forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 1
/
closest-binary-search-tree-value-ii.py
118 lines (104 loc) · 4.27 KB
/
closest-binary-search-tree-value-ii.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Time: O(h + k)
# Space: O(h)
class Solution(object):
def closestKValues(self, root, target, k):
"""
:type root: TreeNode
:type target: float
:type k: int
:rtype: List[int]
"""
# Helper to make a stack to the next node.
def nextNode(stack, child1, child2):
if stack:
if child2(stack):
stack.append(child2(stack))
while child1(stack):
stack.append(child1(stack))
else:
child = stack.pop()
while stack and child is child2(stack):
child = stack.pop()
# The forward or backward iterator.
backward = lambda stack: stack[-1].left
forward = lambda stack: stack[-1].right
# Build the stack to the closest node.
stack = []
while root:
stack.append(root)
root = root.left if target < root.val else root.right
dist = lambda node: abs(node.val - target)
forward_stack = stack[:stack.index(min(stack, key=dist))+1]
# Get the stack to the next smaller node.
backward_stack = list(forward_stack)
nextNode(backward_stack, backward, forward)
# Get the closest k values by advancing the iterators of the stacks.
result = []
for _ in xrange(k):
if forward_stack and \
(not backward_stack or dist(forward_stack[-1]) < dist(backward_stack[-1])):
result.append(forward_stack[-1].val)
nextNode(forward_stack, forward, backward)
elif backward_stack and \
(not forward_stack or dist(backward_stack[-1]) <= dist(forward_stack[-1])):
result.append(backward_stack[-1].val)
nextNode(backward_stack, backward, forward)
return result
class Solution2(object):
def closestKValues(self, root, target, k):
"""
:type root: TreeNode
:type target: float
:type k: int
:rtype: List[int]
"""
# Helper class to make a stack to the next node.
class BSTIterator:
# @param root, a binary search tree's root node
def __init__(self, stack, child1, child2):
self.stack = list(stack)
self.cur = self.stack.pop()
self.child1 = child1
self.child2 = child2
# @return an integer, the next node
def next(self):
node = None
if self.cur and self.child1(self.cur):
self.stack.append(self.cur)
node = self.child1(self.cur)
while self.child2(node):
self.stack.append(node)
node = self.child2(node)
elif self.stack:
prev = self.cur
node = self.stack.pop()
while node:
if self.child2(node) is prev:
break
else:
prev = node
node = self.stack.pop() if self.stack else None
self.cur = node
return node
# Build the stack to the closet node.
stack = []
while root:
stack.append(root)
root = root.left if target < root.val else root.right
dist = lambda node: abs(node.val - target) if node else float("inf")
stack = stack[:stack.index(min(stack, key=dist))+1]
# The forward or backward iterator.
backward = lambda node: node.left
forward = lambda node: node.right
smaller_it, larger_it = BSTIterator(stack, backward, forward), BSTIterator(stack, forward, backward)
smaller_node, larger_node = smaller_it.next(), larger_it.next()
# Get the closest k values by advancing the iterators of the stacks.
result = [stack[-1].val]
for _ in xrange(k - 1):
if dist(smaller_node) < dist(larger_node):
result.append(smaller_node.val)
smaller_node = smaller_it.next()
else:
result.append(larger_node.val)
larger_node = larger_it.next()
return result