# [LeetCode binary tree] search in binary search tree (700)

## 1. Title

Given the root node and a value of a binary search tree (BST). You need to find the node whose node value is equal to the given value in the BST. Returns the subtree with this node as the root. NULL if the node does not exist.

### 1.1 example

• Example 1 1 1 :

• Input: root = [4, 2, 7, 1, 3], val = 2

• Output: [2, 1, 3]

• Example 2 2 2 :

• Input: root = [4, 2, 7, 1, 3], val = 5

• Output: []

### 1.3 restrictions

• The number of nodes in a given binary search tree is [ 1 , 5000 ] [1, 5000] [1,5000] ；
• 1 < = Node.val < = 1 0 7 1 <= \text{Node.val} <= 10^7 1<=Node.val<=107 ；
• 1 < = val < = 1 0 7 1 <= \text{val} <= 10^7 1<=val<=107 .

## 2. Solution I (recursive method)

### 2.1 analysis

Because of the unique property of binary search tree, that is, the val value of any node is greater than that of all nodes in its left subtree and less than that of all nodes in its right subtree; Therefore, the recursive implementation of this problem is very simple, that is, starting from the root node, judge the value to be searched and the val value of the root node (current node) in turn:

• If the former is smaller than the latter, continue to search in the left subtree;
• If the former is greater than the latter, continue to search in the right subtree;
• If the former is equal to the latter, the current node object is returned.

### 2.2 realization

from typing import Optional, List

class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

class Solution:
def __init__(self):
self._node = None

def preorder(self, root: TreeNode) -> List[int]:
if not isinstance(root, TreeNode):
return []
return [root.val] + self.preorder(root.left) + self.preorder(root.right)

def _search(self, root: TreeNode, val: int) -> Optional[TreeNode]:
if not isinstance(root, TreeNode):
return
if root.val > val:
self._search(root.left, val)
elif root.val < val:
self._search(root.right, val)
else:
self._node = root
return

def search(self, root: TreeNode, val: int) -> TreeNode:
self._search(root, val)
return self._node

def main():
node5 = TreeNode(3)
node4 = TreeNode(1)
node3 = TreeNode(7)
node2 = TreeNode(2, left=node4, right=node5)
node1 = TreeNode(4, left=node2, right=node3)
root = node1
sln = Solution()
node = sln.search(root, 2)
print(sln.preorder(node))  # [2, 1, 3]
node = sln.search(root, 4)
print(sln.preorder(node))  # [4, 2, 1, 3, 7]

if __name__ == '__main__':
main()



The above implementation uses a protected method_ Search performs a specific search and uses an instance attribute self_ Node to return the found object to be searched. In fact, this requirement can be simply realized by using only one method:

from typing import Optional, List

class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

class Solution:
def preorder(self, root: TreeNode) -> List[int]:
if not isinstance(root, TreeNode):
return []
return [root.val] + self.preorder(root.left) + self.preorder(root.right)

def succinct_search(self, root: TreeNode, val: int) -> Optional[TreeNode]:
if not isinstance(root, TreeNode):
return
if root.val == val:
return root
if root.val > val:
return self.succinct_search(root.left, val)
else:
return self.succinct_search(root.right, val)

def main():
node5 = TreeNode(3)
node4 = TreeNode(1)
node3 = TreeNode(7)
node2 = TreeNode(2, left=node4, right=node5)
node1 = TreeNode(4, left=node2, right=node3)
root = node1
sln = Solution()
node = sln.succinct_search(root, 2)
print(sln.preorder(node))  # [2, 1, 3]
node = sln.succinct_search(root, 4)
print(sln.preorder(node))  # [4, 2, 1, 3, 7]

if __name__ == '__main__':
main()



### 2.3 complexity

• Time complexity: O ( h ) O(h) O(h), where h h h is the height of the tree. The average time complexity is O ( log ⁡ n ) O(\log n) O(logn), the worst time complexity is O ( n ) O(n) O(n) ；
• Space complexity: O ( h ) O(h) O(h), the depth of recursive stack is h h h . The average depth is O ( log ⁡ n ) O(\log n) O(logn), the worst case depth is O ( n ) O(n) O(n) .

## 3. Solution II (iterative method)

### 3.1 analysis

In order to reduce the space complexity, you can continue to convert the recursive form into iteration, that is, on the premise that the root node is not empty:

• If val == root.val, the root node is returned directly;
• If Val < root.val, enter the left subtree of the root node to find it;
• If Val > root.val, enter the right subtree of the root node.

### 3.2 realization

from typing import Optional, List

class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

class Solution:
def iterative_search(self, root: TreeNode, val: int) -> Optional[TreeNode]:
if not isinstance(root, TreeNode):
return
while root:
if root.val == val:
return root
elif root.val > val:
root = root.left
else:
root = root.right
return root


### 3.3 complexity

• Time complexity: O ( h ) O(h) O(h), where h h h is the height of the tree. The average time complexity is O ( log ⁡ n ) O(\log n) O(logn), the worst time complexity is O ( n ) O(n) O(n) ；
• Space complexity: O ( 1 ) O(1) O(1) .

Tags: Python leetcode

Posted on Sun, 21 Nov 2021 19:27:02 -0500 by upperbid