LeetCode selected TOP interview question 230. The K-smallest element in the binary search tree

Title Description

  • Given the root node of a binary search tree, root, and an integer k
  • Design an algorithm to find the k-th smallest element (counting from 1).
example
input  : root = [3,1,4,null,2], k = 1
output : 1
note   :    3
           / \
          1   4
           \
            2
input  : root = [5,3,6,2,4,null,null,1], k = 3
output : 3
note   :         5
                / \
               3   6
              /  \
             2    4
            /
           1

Problem solving ideas

Idea 1 directly traverse all nodes in middle order

  • Direct recursion, traversing the whole tree in middle order
  • In the recursive process, the node values are stored in the list in turn
  • Because the middle order traversal results of the binary search tree are in ascending order, you can directly return the k-th element value of the list
  • Time complexity: O(H+k), h is the height of the tree. Before starting traversal, you need O(H) to reach the leaf node. When the tree is a balanced tree, the time complexity obtains the minimum value O(logN+k); When the tree is a linear tree (each node in the tree has only one child node or no child node), the time complexity reaches the maximum O(N+k).
  • Space complexity: O(H). At most h elements need to be stored in the stack. When the tree is a balanced tree, the spatial complexity obtains the minimum value O(logN); When the tree is a linear tree, the spatial complexity reaches the maximum O(N).

Idea 2 the first k nodes in the stack simulation

  • In order to reduce the number of traversals, the optimization idea is not to traverse the whole tree, but to stop when traversing the target element by using the nature of binary search tree
  • The recursive process is simulated by stack, and the first k nodes are traversed in middle order
  • Each time (assuming the current is the ith time) the top node of the stack is out of the stack, it indicates that the top node of the stack is the ith small value in the whole tree (determined by the middle order traversal property in binary search)
  • Directly jump out of the traversal and return the node value of the last pop-up stack
  • Time complexity: O(H+k), h is the height of the tree. Before starting traversal, you need O(H) to reach the leaf node. When the tree is a balanced tree, the time complexity obtains the minimum value O(logN+k); When the tree is a linear tree (each node in the tree has only one child node or no child node), the time complexity reaches the maximum O(N+k).
  • Space complexity: O(H). At most h elements need to be stored in the stack. When the tree is a balanced tree, the spatial complexity obtains the minimum value O(logN); When the tree is a linear tree, the spatial complexity reaches the maximum O(N).

Idea 3 record the node number of subtree

  • If you need to frequently find the k-th smallest value, the optimization idea is to record the number of nodes of the subtree with each node as the root node, and constantly narrow the search range when looking for the k-th smallest value
  • Make node equal to the root node and start the search
  • Note that the number of nodes in the left subtree of node is left
  • If left is less than k-1, the element with the smallest K must be in the right subtree of node, make node equal to its right child node, update K to K − left − 1, and continue the search;
  • If left is equal to k-1, the k-th smallest element is node. End the search and return to node;
  • If left is greater than k-1, the element with the smallest K must be in the left subtree of node, make node equal to its left child node, and continue the search.
  • Time complexity: the time complexity of preprocessing is O(N), where N is the total number of nodes in the tree; It is necessary to traverse all nodes in the tree to count the number of nodes of the subtree with each node as the root node. The time complexity of the search is O(H), where HH is the height of the tree; When the tree is a balanced tree, the time complexity gets the minimum value O(logN); When the tree is a linear tree, the time complexity reaches the maximum O(N).
  • Spatial complexity: O(N), used to store the number of nodes of the subtree with each node as the root node.

Idea 3 refers to the official problem solution of LeetCode

Code (Java)

Train of thought 1 code

public class Solution1 {
    List<Integer> list = new ArrayList<>();
    public int kthSmallest(TreeNode root, int k) {
        // Medium order traversal, DFS
        DFS(root);
        for (int i : list) {
            System.out.print(i + " ");
        }
        return list.get(k - 1);
    }

    private void DFS(TreeNode root) {
        if (root == null) {
            return;
        }
        DFS(root.left);
        list.add(root.val);
        DFS(root.right);
    }
}

Train of thought 2 code

public class Solution2 {
    public int kthSmallest(TreeNode root, int k) {
        // Using stack simulation to realize middle order traversal
        Stack<TreeNode> stack = new Stack<>();
        // It is necessary to ensure that the smallest element is used as the first stack element, so the root node cannot be pushed into the stack outside the loop, so | root is added to the boundary condition of the loop= Null condition
        while (!stack.isEmpty() || root != null) {
            while (root != null) {
                stack.add(root);
                root = root.left;
            }
            root = stack.pop();
            System.out.print(root.val + " ");
            k--;
            // The value of the kth pop-up stack node must be the smallest k
            if (k == 0) {
                break;
            }
            root = root.right;
        }
        return root.val;
    }
}

Train of thought 3 code

public class Solution3 {
    public int kthSmallest(TreeNode root, int k) {
        MyBst myBst = new MyBst(root);
        return myBst.kthSmallest(k);
    }
}

class MyBst {
    TreeNode root;
    Map<TreeNode, Integer> nodeNumber;

    public MyBst(TreeNode root) {
        this.root = root;
        this.nodeNumber = new HashMap<TreeNode, Integer>();
        countNumber(root);
    }

    // Count the number of nodes of subtrees with node as the root node
    private int countNumber(TreeNode node) {
        if (node == null) {
            return 0;
        }
        nodeNumber.put(node, countNumber(node.left) + countNumber(node.right) + 1);
        return nodeNumber.get(node);
    }

    // Returns the k-th smallest element in the binary search tree
    public int kthSmallest(int k) {
        TreeNode node = root;
        while (node != null) {
            int left = getNumber(node.left);
            if (left == k - 1) {
                break;
            } else if (left > k - 1) {
                node = node.left;
            } else {
                node = node.right;
                k = k - left - 1;
            }
        }
        return node.val;
    }

    private int getNumber(TreeNode node) {
        return nodeNumber.getOrDefault(node, 0);
    }
}

Tags: leetcode Binary tree dfs

Posted on Mon, 29 Nov 2021 12:23:29 -0500 by Brendan