[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.2 description

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