題目出處
901 · Closest Binary Search Tree Value II
難度
hard
個人範例程式碼
from typing import (
List,
)
from lintcode import (
TreeNode,
)
"""
Definition of TreeNode:
class TreeNode:
def __init__(self, val):
self.val = val
self.left, self.right = None, None
"""
class Solution:
"""
@param root: the given BST
@param target: the given target
@param k: the given k
@return: k values in the BST that are closest to the target
we will sort your return value in output
"""
def closest_k_values(self, root: TreeNode, target: float, k: int) -> List[int]:
if not root or k == 0:
return []
# write your code here
lower_stack = self.get_stack(root, target) # init to found target
upper_stack = list(lower_stack)
# delete duplicate closest element, change wrong lower[-1] or upper[-1]
if lower_stack[-1].val < target:
self.move_upper(upper_stack)
else:
self.move_lower(lower_stack)
ans = []
for i in range(k):
if self.is_lower_closer(lower_stack, upper_stack, target):
ans.append(lower_stack[-1].val)
self.move_lower(lower_stack)
else:
ans.append(upper_stack[-1].val)
self.move_upper(upper_stack)
return ans
def is_lower_closer(self, lower_stack, upper_stack, target):
if not lower_stack: # has nothing
return False
if not upper_stack:
return True
return target - lower_stack[-1].val < upper_stack[-1].val - target
def move_lower(self, stack):
if stack[-1].left: # has left, move to the right bottom
node = stack[-1].left
while node:
stack.append(node)
node = node.right
else: # no left, move to the first turn right parent
node = stack.pop()
while stack and stack[-1].left == node:
node = stack.pop()
def move_upper(self, stack):
if stack[-1].right: # has right, move to the left bottom
node = stack[-1].right
while node:
stack.append(node)
node = node.left
else: # no right, move to the first turn left parent
node = stack.pop()
while stack and stack[-1].right == node:
node = stack.pop()
def get_stack(self, root, target):
stack = []
while root:
stack.append(root)
if target <= root.val:
root = root.left
else:
root = root.right
return stack
算法說明
BST iteration 集大成的最難題目,能考的都考了。
這題最難的部分在於實作 iteration (當然,要重新 traverse 絕對是更簡單的方法,不過速度上會慢),
分成兩種狀況討論:
- 往更小「一個」移動
- 往更大「一個」移動
往更小「一個」移動
說到小,就先想到 left
這裡又分成兩種情況,
- 如果有 left,往 left 的 最右底點移動 (才會是「第一個」更小)
- 如果沒有 left,找第一個 edge 右彎的 parent
看不懂就看下圖可能會比較好懂… 一點點XD
往更大「一個」移動
說到大,就先想到 right
這裡又分成兩種情況,
- 如果有 right,往 right 的 最左底點移動 (才會是「第一個」更大)
- 如果沒有 right,找第一個 edge 左彎的 parent
看不懂就看下圖可能會比較好懂… 一點點XD
最近在練習程式碼本身就可以自解釋的 Coding style,可以嘗試直接閱讀程式碼理解
input handling
當 k = 0 或是沒有 root 時,return []
Boundary conditions
見上述說明
