Given two integer arrays preorder
and inorder
containing the preorder and inorder traversals of a binary tree, construct the binary tree, and return its root. The values in the traversals will all be unique.
Example:
We want to create a function that takes in preorder and inorder, and returns the root node of the tree.
1. Recursion
To make this function recursive, buildTree should call itself to construct the root.left and root.right nodes. You can draw the recursion visually as:
The next thing we have to do is figure out what pL, iL, pR, iR and v are. Here's a visual of how to do this - the idea is to look back and forth between the two arrays until we find everything:
We have everything we need for the recursion. Here's the recursion:
2. Base case
The recursion calls itself on smaller and smaller arrays, since it keeps splicing the input. The smallest case is when we get to two empty arrays - at this point, it means we're building a null node. (Note that the arrays will always be the same size).
3. Code
To code this, we just have to do is combine the recursion and base case:
Time Complexity O(n2). We visit each of the n nodes once. At each node, we create the arrays pL,pR,iL,iR which all take O(n) operations. We also call inorder.index(v) which is also O(n). Adding this all up, the total operations per function call is O(5n) and we call the function n times. This means the total time is O(5n)∗n=O(n2).
Space Complexity O(n2). The Call Stack grows to the height of the tree, which is n. Each call in the Call Stack needs to remember its inputs, which are both size O(n) arrays. This gives O(n2) memory.
This solution should pass in an interview (I got a FAANG job with it), but you can make some optimizations. If you're curious what they are, see the spoiler below.
One problem is that it takes O(n) time to call inorder.index(), which is slow. We can instead compute all the results in a HashMap before we start, which means we don't have to call inorder.index(), and can instead just look the results up in O(1) time.
Another problem is that the function has arrays as inputs, which takes up O(n) memory. We can instead use numbers as inputs, which only use O(1) memory.
Here's how you do both of these:
Time Complexity O(n). We need to go through all the nodes in the tree.
Space Complexity O(n). The Call Stack still grows to a height of n, but now each call in the call stack needs to store indices, which are just O(1) memory. This gives O(n) memory.