Convert sorted array to binary tree in Java - java

Given a sorted array, convert it into a binary search tree in Java (Leetcode problem)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
if(nums.length == 0) {return null;}
TreeNode ans = helper(nums, 0, nums.length);
return ans;
}
public TreeNode helper(int [] nums, int start, int end){
int mid = start + (end - start)/2;
if(start == end){
TreeNode lastNode = new TreeNode(nums[start]);
lastNode.right = null;
lastNode.left = null;
return lastNode;
}
int mi = nums[mid];
TreeNode newNode = new TreeNode(mi);
TreeNode left = helper(nums, start, mid - 1);
TreeNode right = helper(nums, mid + 1, end);
newNode.left = left;
newNode.right = right;
return newNode;
}
}
I get a stackoverflowerror at the line:
TreeNode left = helper(nums, start, mid - 1);
But I don't see why I get the error?
I tried it out with the sample array: [1, 2, 3] and I got the error. Can someone help me out on why this is happening?

That is because the condition (start == end) doesn't happens and recursive still calling
Try to make it (nums.length -1) instead of nums.length

I've modified code to make it work. At first, I've uncommented the enclosing TreeMode class and made Solution as inner class. Then I've removed public keyword from class declarations due to compilation error.
I've added more arguments for TreeNode constructor. To create a TreeNode object called root, a constructor is called with three arguments by the new operator inside method helper of the class Solution. Added if-condition inside helper method to avoid Memory Limit Exceeded.
And changed nums.length parameter to nums.length-1. As correctly mentioned by Fady Saad.
An algorithm needs to take the element from the middle of an array and put it as the root node. And, after that, an array is divided into a left and right side. The central element of the left side becomes a left node, while the central element of the right side of the table becomes the right node.
To understand and analyze deeply, you can debug it.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x, TreeNode y, TreeNode z) {
val = x;
left = y;
right = z;
}
}
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
if (nums.length == 0) {
return null;
}
TreeNode ans = helper(nums, 0, nums.length - 1);
return ans;
}
public TreeNode helper(int[] nums, int start, int end) {
if (start > end) {
return null;
}
int mid = (start + end) / 2;
TreeNode root = new TreeNode(nums[mid], null, null);
root.left = helper(nums, start, mid - 1);
root.right = helper(nums, mid + 1, end);
return root;
}
}

Related

Converted sorted array to a height-balanced binary search tree

I'm solving leetcode problem to convert a sorted integer array to a binary search tree. A height-balanced binary tree is a binary tree in which the depth of the two subtrees of every node never differs by more than one.
Recursive solution is fairly straightforward, but iterative solution seems to be much more complicated. I came up with the following pretty sub-optimal and not that concise implementation:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode() {}
public TreeNode(int val) { this.val = val; }
public TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
private static int[] leftNode(int[] arr){
return Arrays.copyOfRange(arr, 0, arr.length / 2);
}
private static int[] rightNode(int[] arr){
return Arrays.copyOfRange(arr, arr.length / 2 + 1, arr.length);
}
private static int root(int arr[]){
return arr[arr.length / 2];
}
public static TreeNode sortedArrayToBstIterative(int[] nums){
if(nums == null || nums.length == 0){
return null;
}
TreeNode root = new TreeNode(root(nums));
List<int[]> parts = Arrays.asList(leftNode(nums), rightNode(nums));
List<TreeNode> level = Collections.singletonList(root);
int notVisited = nums.length - 1;
while(notVisited > 0){
List<TreeNode> nextLevel = new ArrayList<>();
List<int[]> nextParts = new ArrayList<>();
Iterator<int[]> iterator = parts.iterator();
for(TreeNode node: level){
int[] left = iterator.hasNext() ? iterator.next() : null;
if(left != null && left.length != 0){
TreeNode leftNode = new TreeNode(root(left));
node.left = leftNode;
nextLevel.add(leftNode);
nextParts.add(leftNode(left));
nextParts.add(rightNode(left));
notVisited--;
}
int[] right = iterator.hasNext() ? iterator.next() : null;
if(right != null && right.length != 0){
TreeNode rightNode = new TreeNode(root(right));
node.right = rightNode;
nextLevel.add(rightNode);
nextParts.add(leftNode(right));
nextParts.add(rightNode(right));
notVisited--;
}
}
parts = nextParts;
level = nextLevel;
}
return root;
}
The solution is basically about splitting the given array into 2 subarrays until all of the elements are used.
It works fine, but the question is if there's another more concise solution to produce height-balanced binary search tree?
Don't write, never commit or publish undocumented code:
In Java, use doc comments.
You create a lot of arrays.
Give using java.util.Arrays.asList() & List.subList(from, to) a try.
As a complete binary tree is balanced enough, that should be easier to construct.

Why is recursion causing the count to return 2 instead of 4?

I am trying to do the Balanced Tree question on Leetcode where you return true only if height of left subtree - height of right subtree <= 1.
Why is the depth of the left subtree returning a 2 when it should return 4? Is there something I am interpreting wrongly? I attached a picture of the tree at the bottom.
Input: [1,2,2,3,3,null,null,4,4,null,null,5,5]
Output: True (because left subtree is returning 2 instead of 4)
Expected Output: False
Print Statements:
left subtree: 2
right subtree: 1
result: 1 (left subtree - right subtree)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
// 1 2 2 3 3 4 4
//
if (root == null) return true;
System.out.println("left subtree: " + findDepth(root.left,1));
System.out.println("right subtree: " + findDepth(root.right,1));
System.out.println("result: " + Math.abs(findDepth(root.left,1) - findDepth(root.right, 1)));
if ( Math.abs(findDepth(root.left,1) - findDepth(root.right, 1)) <= 1) return true;
return false;
}
public static int findDepth(TreeNode root, int count) {
if (root == null) return count;
if (root.left != null) {
count++;
findDepth(root.left, count);
}
if(root.left == null && root.right == null) return count;
return count;
}
}
Image of Binary Tree
The reason why you get 2 is because when you recurse, the recursive call is not incrementing the count variable that you pass in. Instead, it increments its own copy of it. Java is pass by value.
if (root.left != null) {
count++;
// the call below will not change "count" at all
findDepth(root.left, count);
// it will only change its own copy
}
Therefore, the recursive call practically does nothing. You are not even using its return value. Its return value is actually the modified copy of count that you want count to be set to, so to fix this, set count to the return value of findDepth:
value = findDepth(root.left, count);
This will give you the expected 4, but your findDepth should also check the right subtree, and can be improved in other ways. For example, you don't actually need a count argument.
public static int findDepth(TreeNode root) {
if (root == null) return 0;
return 1 + Math.max(findDepth(root.left), findDepth(root.right));
}
Because you are only counting the depth of the left side of the tree in findDepth methof by applying condition
if (root.left != null) {
count++;
findDepth(root.left, count);
}
You can modify your method like this
public static int findDepth(TreeNode root, int count) {
if (root == null) return count;
return Math.max(findDepth(root.left, count+1),findDepth(root.right, count+1));
}

Rewrite a C code in Java to construct full binary tree

I want to write a function to construct a full binary tree from a given preorder and postorder array. I found that link http://www.geeksforgeeks.org/full-and-complete-binary-tree-from-given-preorder-and-postorder-traversals/ which proposes the following C code :
struct node* constructTreeUtil (int pre[], int post[], int* preIndex,
int l, int h, int size)
{
// Base case
if (*preIndex >= size || l > h)
return NULL;
// The first node in preorder traversal is root. So take the node at
// preIndex from preorder and make it root, and increment preIndex
struct node* root = newNode ( pre[*preIndex] );
++*preIndex;
// If the current subarry has only one element, no need to recur
if (l == h)
return root;
// Search the next element of pre[] in post[]
int i;
for (i = l; i <= h; ++i)
if (pre[*preIndex] == post[i])
break;
// Use the index of element found in postorder to divide postorder array in
// two parts. Left subtree and right subtree
if (i <= h)
{
root->left = constructTreeUtil (pre, post, preIndex, l, i, size);
root->right = constructTreeUtil (pre, post, preIndex, i + 1, h, size);
}
return root;
}
// The main function to construct Full Binary Tree from given preorder and
// postorder traversals. This function mainly uses constructTreeUtil()
struct node *constructTree (int pre[], int post[], int size)
{
int preIndex = 0;
return constructTreeUtil (pre, post, &preIndex, 0, size - 1, size);
}
I tried to rewrite this code in Java. Here is my code :
private static TreeNode constructTree(int[] preorder, int[] postorder, Index index, int lowIndex, int highIndex){
// Base case
if (index.index >= preorder.length || lowIndex > highIndex){
return null;
}
// The first node in preorder traversal is root. So take the node at
// preIndex from preorder and make it root, and increment preIndex
TreeNode root = new TreeNode (preorder[lowIndex]);
index.index++;
// If the current subarry has only one element, no need to recur
if (lowIndex == highIndex){
return root;
}
// Search the next element of pre[] in post[]
int i = 0;
for (i = lowIndex; i <= highIndex; ++i)
if (preorder[i]== postorder[lowIndex])
break;
// Use the index of element found in postorder to divide postorder array in
// two parts. Left subtree and right subtree
if (i <= highIndex) {
root.left = constructTree(preorder, postorder, index, lowIndex, i);
root.right = constructTree(preorder, postorder, index, i + 1, highIndex);
}
return root;
}
//The main function to construct Full Binary Tree from given preorder and
//postorder traversals. This function mainly uses constructTreeUtil()
public static TreeNode constructTree (int preorder[], int postorder[]) {
return constructTree (preorder, postorder, new Index(), 0, preorder.length - 1);
}
But I got a continuous loop in the root node (it didn't pass to the other nodes which have to be its child). Can you help me please to see where is the error in my Java code?
I'm not really sure but I think that the error maybe comes from these lines :
int i = 0;
for (i = lowIndex; i <= highIndex; ++i)
if (preorder[i]== postorder[lowIndex])
break;
I didn't understand very well the correspond lines in the original C code. Especially in this part
Here are the bugs:
Line if (preorder[i]== postorder[lowIndex]) has two errors: the first is that you search in preorder instead of in postorder, and the second is that you use lowIndex instead of preIndex.
This line should be: if (preorder[index.index]== postorder[i])
Line TreeNode root = new TreeNode (preorder[lowIndex]); - lowIndex is used again instead of preIndex.
This line should be: TreeNode root = new TreeNode (preorder[index.index]);
Pay attention to the fact that this code would work only for full binary trees
Assuming that your code written in C works, then my guess is that for this part
// Search the next element of pre[] in post[]
int i = 0;
for (i = lowIndex; i <= highIndex; ++i)
if (preorder[i]== postorder[lowIndex])
break;
you'd want to use the same variables that you use in the C version. In this case, your if statement should be
if (preorder[index.index]== postorder[i])
First make your TreeNode into a class, since it is the java equivalent of a struct
public class TreeNode{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val){
this.val = val;
}
}
Then make your TreeUtil class
public class TreeUtil{
private static TreeNode constructTree(int[] preorder, int[] postorder, int index, int lowIndex, int highIndex){
// Base case
if (index >= preorder.length || lowIndex > highIndex){
return null;
}
// The first node in preorder traversal is root. So take the node at
// preIndex from preorder and make it root, and increment preIndex
TreeNode root = new TreeNode (preorder[index]);
index++;
// If the current subarry has only one element, no need to recur
if (lowIndex == highIndex){
return root;
}
// Search the next element of pre[] in post[]
for (int i = lowIndex; i <= highIndex; i++)
if (preorder[index]== postorder[i]){
// Use the index of element found in postorder to divide postorder array in
// two parts. Left subtree and right subtree
root.left = constructTree(preorder, postorder, index, lowIndex, i);
root.right = constructTree(preorder, postorder, index, i + 1, highIndex);
break;
}
}
return root;
}
//The main function to construct Full Binary Tree from given preorder and
//postorder traversals. This function mainly uses constructTreeUtil()
public static TreeNode constructTree (int preorder[], int postorder[]){
return constructTree (preorder, postorder, 0, 0, preorder.length - 1);
}
}
Errors in your code were if (preorder[i]== postorder[lowIndex] and TreeNode root = new TreeNode (preorder[lowIndex]); as mentioned by aviad. I changed your code for you to be slightly less confusing. Using the Index is a great way to confuse yourself especially since an int will work fine. Also ++i increments before you run the loop and isn't conventionally used in java and java lets you declare variables a part of your loop definition so I changed that for loop to be more what your are looking for.

Iterative Solution to finding if a tree is balanced

So someone posted their solution to this, but I found that it didn't seem to work, I posted this there but I wanted to make it more accessible to others.
The question is in "Cracking the Code Interview" and it is the first tree question, feel free to make other suggestions (or prove me wrong!)
The key here is that it is difficult to keep track of the eventual paths and their heights with one stack.
What I ended up doing is pushing both the left and right child's height on a stack, checking if they are within one of one another, adding one to the max and then pushing that onto the stack after popping the left and right off.
I have commented so I hope it's clear enough
/* Returns true if binary tree with root as root is height-balanced */
boolean isBalanced(Node root) {
if(root == null) return false;
Deque<Integer> heights = new LinkedList<>();
Deque<Node> trail = new LinkedList<>();
trail.push(root);
Node prev = root; //set to root not null to not confuse when root is misisng children
while(!trail.isEmpty()) {
Node curr = trail.peek(); //get the next node to process, peek because we need to maintain trail until we return
//if we just returned from left child
if (curr.left == prev) {
if(curr.right != null) trail.push(curr.right); //if we can go right go
else {
heights.push(-1); //otherwise right height is -1 does not exist and combine heights
if(!combineHeights(heights)) return false;
trail.pop(); //back to parent
}
}
//if we just returned from right child
else if (curr.right == prev) {
if(!combineHeights(heights)) return false;
trail.pop(); //up to parent
}
//this came from a parent, first thing is to visit the left child, or right if no left
else {
if(curr.left != null) trail.push(curr.left);
else {
if (curr.right != null) {
heights.push(-1); //no left so when we combine this node left is 0
trail.push(curr.right); //since we never go left above logic does not go right, so we must here
}
else { //no children set height to 1
heights.push(0);
trail.pop(); //back to parent
}
}
}
prev = curr;
}
return true;
}
//pop both previous heights and make sure they are balanced, if not return false, if so return true and push the greater plus 1
private boolean combineHeights(Deque<Integer> heights) {
int rightHeight = heights.pop();
int leftHeight = heights.pop();
if(Math.abs(leftHeight - rightHeight) > 1) return false;
else heights.push(Math.max(leftHeight, rightHeight) + 1);
return true;
}
So in the end I managed to create an iterative solution which works for all test cases on Leetcode
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public static boolean isBalanced(TreeNode root) {
if (root == null) return true;
Deque<Pair> queue = new LinkedList<>();
queue.offer(new Pair(root, 0));
while (!queue.isEmpty()) {
var curr = queue.poll();
System.out.printf(">>Curr node is %s and curr.lvl is %s", curr.node.val, curr.lvl);
int left = getSubTreeHeight(new Pair(curr.node.left, curr.lvl + 1));
int right = getSubTreeHeight(new Pair(curr.node.right, curr.lvl + 1));
if (Math.abs(left - right) > 1) return false;
if (curr.node.left != null) queue.offer(new Pair(curr.node.left, curr.lvl + 1));
if (curr.node.right != null) queue.offer(new Pair(curr.node.right, curr.lvl + 1));
}
return true;
}
static int getSubTreeHeight(Pair pair) {
if (pair.node == null) {
return pair.lvl -1;
}
Deque<Pair> queue = new LinkedList<>();
queue.offer(pair);
int height = 0;
while (!queue.isEmpty()) {
Pair curr = queue.poll();
System.out.printf("Curr node is %s and curr.lvl is %s", curr.node.val, curr.lvl);
height = curr.lvl;
if (curr.node.left != null) queue.offer(new Pair(curr.node.left, curr.lvl + 1));
if (curr.node.right != null) queue.offer(new Pair(curr.node.right, curr.lvl + 1));
}
return height;
}
public static class Pair {
TreeNode node;
int lvl;
public Pair(TreeNode node, int lvl) {
this.node = node;
this.lvl = lvl;
}
}
}
The original question in the book does not mention the tree being binary. I happen to solve the same question, but coded in Python. So, here is my iterative solution for the problem, for general trees (where the children of a node is stored in a list), in python.
def is_balanced_nonrecursive(self):
stack = [self.root]
levels = [0]
current_min = sys.maxint
current_max = 0
current_level = 0
while len(stack) > 0:
n = stack.pop()
current_level = levels.pop()
for c in n.children:
stack.append(c)
levels.append(current_level + 1)
if len(n.children) == 0:
if current_level < current_min:
current_min = current_level
if current_level > current_max:
current_max = current_level
return current_max - current_min < 2
This is basically a depth first traversal of the tree. We keep a separate stack for the levels (the list levels). If we see any leaf node, we update the current min and current max levels accordingly. The algorithm traverses the whole tree and at the end if max and min levels differ by more than one, then the tree is not balanced.
There are many optimizations possible, like for instance checking whether the difference of min and max is more than one inside the loop, and if that is the case return False immediately.
Some code repetition on this one, but at least it doesn't give me a headache as the recursive ones do:
public boolean isBalanced() {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
int leftLevel = 0;
int rightLevel = 0;
if(this == null) return false;
if(this.left != null)queue.offer(this.left);
while(!queue.isEmpty()) {
int size = queue.size();
for(int i=0; i < size; i++) {
if(queue.peek().left != null) queue.offer(queue.peek().left);
if(queue.peek().right != null) queue.offer(queue.peek().right);
queue.poll();
}
leftLevel++;
}
if(this.right != null) queue.offer(this.right);
while(!queue.isEmpty()) {
int size = queue.size();
for(int i=0; i < size; i++) {
if(queue.peek().left != null) queue.offer(queue.peek().left);
if(queue.peek().right != null) queue.offer(queue.peek().right);
queue.poll();
}
rightLevel++;
}
return Math.abs(leftLevel - rightLevel) < 2;
}

Using a recursive method to find the smallest element in a subtree given the root: what am I doing wrong here?

So I have a homework question where I'm supposed to use a recursive method to "find the minimum element within a subtree rooted at the specified node"
And then I'm given this as my starting point:
public TreeNode
{
int data;
TreeNode left;
TreeNode right;
}
and
/**
Finds the minimum value for the subtree that is
rooted at a given node
#param n The root of the subtree
#return The minimum value
PRECONDITION: n is not null.
*/
int min(TreeNode n)
{
// COMPLETE THE BODY OF THIS METHOD
}
Now, I've got a very basic driver program written to insert nodes into the tree and I've written my recursive method, but it seems to be counting up instead of down, here's my method:
int min(TreeNode n){
if(n.left != null) {
n = n.left;
min(n);
System.out.println("N is now " + n.value);
}
return n.value;
}
Output of my code:
Building tree with rootvalue 25
=================================
Inserted 11 to left of node 25
Inserted 15 to right of node 11
Inserted 16 to right of node 15
Inserted 23 to right of node 16
Inserted 79 to right of node 25
Inserted 5 to left of node 11
Inserted 4 to left of node 5
Inserted 2 to left of node 4
Root is 25
N is now 2
N is now 4
N is now 5
N is now 11
The minimum integer in the given nodes subtree is: 11
Can someone please explain to me why this doesn't work?
Note: this is all assuming you're in a Binary Search Tree, so returning the minimum element means returning the left-most element.
This means your recursive call is quite simple:
min(node):
if this node has a left node:
return min(node.left)
if this node does not have a left node:
return this node's value
The logic is that if we don't have another left node then we are the left-most node, so we are the minimum value.
Now, in Java:
int min(TreeNode n){
if (n.left == null)
return n.value;
return min(n.left); // n.left cannot be null here
}
Now to explain your results, consider how this method works. It calls the method on the next node (min(n.left)) before continuing. In your case you had a println after this recursive call. Therefore the println inside the recursive call went first. So your prints started at the bottom of the tree and worked their way back up. This explains the "reverse order" printing.
Your method then returned 11 as your result because (as another answer has explained) your n = n.left didn't affect any of your recursive sub-calls, only the one in the current function call. This means you returned the left node of the root, rather than the furthest left child.
I hope this makes sense. If you need clarification on anything leave a comment or something. Recursion can be quite tricky to get your head around at first.
The issue is that Java is call-by-value, not by reference -- although references are passed by value. But what that really means in this case is that the call to min(n) does not change what the variable n refers to -- it doesn't do anything at all. What you should probably be doing is return min(n).
public static void main(String[] args) throws IOException, NoSuchMethodException, InitializationError {
Logger.getRootLogger().addAppender(new ConsoleAppender(new SimpleLayout(), "System.out"));
Logger.getRootLogger().setLevel(Level.ALL);
TreeNode n1 = new TreeNode();
TreeNode n2 = new TreeNode();
TreeNode n3 = new TreeNode();
TreeNode n4 = new TreeNode();
TreeNode n5 = new TreeNode();
TreeNode n6 = new TreeNode();
n1.data = 110;
n1.left = n2;
n1.right = n3;
n2.data = 15;
n2.left = n4;
n2.right = null;
n3.data = 3;
n3.left = null;
n3.right = null;
n4.data = 4;
n4.left = null;
n4.right = n5;
n5.data = 12;
n5.left = n6;
n5.right = null;
n6.data = 19;
n6.left = null;
n6.right = null;
System.out.print("min=" + min(n1));
}
static public class TreeNode {
int data;
TreeNode left;
TreeNode right;
}
static int min(TreeNode n) {
return min(n, n.data);
}
static int min(TreeNode n, int min) {
System.out.println("N is now " + n.data);
int currentMin = min;
if (n.left != null && n.right != null) {
final int left = min(n.left);
final int right = min(n.right);
if (left < right) {
currentMin = left;
} else {
currentMin = right;
}
} else if (n.left != null) {
currentMin = min(n.left);
} else if (n.right != null) {
currentMin = min(n.right);
}
if (currentMin < min) {
return currentMin;
} else {
return min;
}
}
OUTPUT is:
N is now 110
N is now 15
N is now 4
N is now 12
N is now 19
N is now 3
min=3
You need to use some tree traversal algoritm, for checking every node of the tree. Also you need to store current finded minimum. Pass this minimum into recursive function. It is calling "accumulator".
The last statement in your method implementation returns the node n's value. As n starts with the root and is replaced by its left child (if exists) you always get the value of the root's left child.
The following code should do it:
int min(final Tree n){
int result;
if(n == null){
result = Integer.MAX_VALUE;
} else {
result = n.value;
final int leftResult = min(n.left);
if(leftResult < result){
result = leftResult;
}
final int rightResult = min(n.right);
if(rightResult < result){
result = rightResult;
}
}
return result;
}
Or you could use the Visitor pattern (you would need to make your tree Iterable then and pass the values to the Visitor one-by-one):
interface TreeVisitor {
void accept(int value);
}
class MinTreeVisistor implements TreeVisitor {
int min = Integer.MAX_VALUE;
#Override
public void accept(int value) {
if(value < this.min) {
this.min = value;
}
}
}

Categories

Resources