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.2 description
- Source: LeetCode
- Link: https://leetcode-cn.com/problems/search-in-a-binary-search-tree
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) .