Determine size of Integer Binary Tree via recursion - java

I have the classes BinaryTreeNode(int value) with its left and right child and BinaryTree(int rootVal) with BinaryTreeNode root with rootVal as its value.
I developed a code to calculate the number of nodes in the tree (in class BinaryTreeNode), but it doesn't work because of a NullPointerException:
public int size(){
if(this == null) { // base case
return 0;
} else {
return 1 + left.size() + right.size();
}
}
However another solution I found, with a similar strategy, works:
public int size(BinaryTreeNode refNode){
if(refNode == null) { // base case
return 0;
} else {
return 1 + size(refNode.left) + size(refNode.right);
}
}
I have understood why my code throws an exception (it is because left/right would point to null).
But I would like to understand why the second solution works with quasi the same principle.
Thank you in advance!

In your first example you try to find the size before you check for null:
first you call
left.size()
and then inside the size() method you check to see if the object you just called the method on is null
if(this == null) { // base case
return 0;
...
so if left is null, you get the NPE before you get into the size() method.
The main thing to remember here, is that this can never be null. If it was, you couldn't be running a method on it in the first place. So you weren't actually terminating your recursion on a null case like you thought you were.
In the second you check for null first:
if refNode.left is null here
return 1 + size(refNode.left) + size(refNode.right);
the size() method does a pre-check
if(refNode == null) { // base case
return 0;
...
and safely returns 0.
You could make your first method work by explicitly putting the null-check first on each branch:
public int size(){
return 1
+ left == null ? 0 : left.size() // check for null first
+ right == null ? 0 : right.size(); // check for null first
}

The base case is organized in the wrong way; checking for null on the current instance makes no sense. The method should be rewritten as follows.
public int size(){
int sizeLeft = 0;
if (this.left != null)
sizeLeft = left.size();
int sizeRight = 0;
if (this.right != null)
sizeRight = right.size();
return 1 + sizeLeft + sizeRight;
}

this can never be null inside the running class. You'll be getting a NPE because a Node with left == null or right == null will not be able to call the size() code, because the pointer refers to nothing.
Perhaps your code should be more defensive and check if the children are null before attempting to retrieve their size:
public int size() {
int total = 1;
if (left != null)
total += left.size();
if (right != null)
total += right.size();
return total;
}

Related

Sort Users using Insertion Sort

I am trying to sort users in ascending order when I search for the users in our UI. I started the approach with Insertion Sort and I currently have something like this:
if (CollectionUtils.isNotEmpty(userList)) {
//Sort by ascending by display name
for (int i=1; i<userList.size(); i++){
User key = userList.get(i);
int j = i-1;
System.out.println("I: "+key.getFirstName());
System.out.println("J: "+userList.get(j).getFirstName());
while (j>-1 && isAscending(key.getFirstName(), userList.get(j).getFirstName())){
User temp = userList.get(j+1);
System.out.println("TEMP: "+temp.getFirstName());
userList.add(j+1, userList.get(j));
userList.add(j, temp);
j--;
}
userList.add(j+1, key);
}
for (final User user : userList) {
beanList.add(UserBean.getInstance(user));
}
}
Assuming that we have nulls, my isAscending method checks for that and the idea is that the users who's name is null will be placed at the bottom of the list:
private boolean isAscending(String left, String right){
if(left.equals(right)) return false;
if(left == null && right == null) return false;
if((left == null && right != null) || left != null && right == null){
return false;
}
if(left.toLowerCase().compareTo(right.toLowerCase())>0){
return true;
}
return false;
}
With these 2 methods I want to be able to sort users in an ascending order based on their first name. Currently I am running into an infinite loop as after the first iteration, the user at the first index is being compared to himself (aka the user at the first index) over and over again.
Any suggestion would be welcome. Thanks
One of your problems is that you keep adding stuff to the list, but you never remove anything. For example, your inner loop is:
while (j>-1 && isAscending(key.getFirstName(), userList.get(j).getFirstName())){
User temp = userList.get(j+1);
System.out.println("TEMP: "+temp.getFirstName());
userList.add(j+1, userList.get(j));
userList.add(j, temp);
j--;
}
Let's say the list contains [3,2,1]. So the first time through you get:
temp = userList.get(1) // so temp = 2
userList.add(1, 3); // this makes the list contain [3,3,2,1]
userList.add(j, temp) // result: [2,3,3,2,1]
You want to swap the values at locations j and j+1. So write:
temp = userList.get(j+1);
userList.set(j+1, userList.get(j));
userList.set(j, temp);
Also, you probably should fix your isAscending method. Currently, you're calling equals on a potentially null reference. Also, there's no reason to call toLowerCase on the parameters to compareTo when you can easily call compareToIgnoreCase. A cleaner comparison method is:
private boolean isAscending(String left, String right){
// if either parameter is null, then not ascending
if(left == null || right == null) return false;
return (left.compareToIgnoreCase(right) > 0);
}
You might reconsider the null handling logic in your code. Does it really make sense for there to be null values for the fields you're comparing? If not, then you probably should have the comparison method throw an exception.
If you do want to support null values, then you need to modify your isAscending method because the current logic makes any non-null value equal to any null value. So if your list contained [3,null,1], then sorting it would return the same order because calling isAscending(3, null) will return false, and so will isAscending(null, 1). If you want to sort nulls to the front, you want this:
// both values are null, so not ascending
if (left == null && right == null) return false;
// left is null, but right is not
if (left == null) return true;
// right is null, but left is not
if (right == null) return false;
return (left.compareToIgnoreCase(right) > 0);

Confirm code that returns nodes with two children

I was given the following code that is supposed to determine the number of nodes in a tree that have two children...
public int twoChildren(TreeNode<Integer> root){
int counter= 0;
if (root == null)
return 0;
else if (root.right != null && root.left != null)
counter++;
int leftTwoChildren = twoChildren(root.left);
int rightTwoChildren = twoChildren(root.right);
return counter + leftTwoChildren + rightTwoChildren;
}
My job is to identify if this code is doing that, and if it isn't then figure out what the issue is. It all seems to check out with me, but I just wanted to double check that the counter works on this example. Would I even need the two integers for the left and right? I'm not sure. If someone could confirm this checks out or let me know there's an issue I would greatly appreciate it.
Your code will work fine if you return 0 instead of null
if(root==null)
return 0;
You don't need the two integers for left and right, you can return the recursive calls explicitly, and also get rid of counter integer.
public int twoChildren(TreeNode<Integer> root){
if (root == null)
return 0;
if (root.right != null && root.left != null)
return 1 + twoChildren(root.left) + twoChildren(root.right);
return twoChildren(root.left) + twoChildren(root.right);
}

Java: Getting if there is an element before a specified element in an ArrayList

public static boolean isComponentBefore(GuiInterface component) {
int index = 0;
for (int i = 0; i < components.size(); i++) {
if (components.get(i).getName() == component.getName()) {
if(components.get(i- 1) == null){
return false;
}
}
}
return true;
}
I currently use this, though this can lead to ConcurrentModificationExceptions & it isn't working because it keeps throwing ConcurrentModificationExceptions whenever I try to see if the element before the element passed in is null.
I was wondering if there are other ways to do this.
Looking at your logic, you will a NullPointerException incase the component in the ArrayList before the given component is null, because components.get(i) would be null and components.get(i).getName() will throw the NPE.
You can try to change the logic here a bit. For every null element in the list, check if the next component is the component you're searching for and return accordingly.
for (int i = 0; i < components.size(); i++) {
if (components.get(i) == null) { // If a particular element is null, check if the next element is what you want
if(components.get(i+1).getName().equals(component.getName())) { // you need to handle the edge case for i+1 as well for the last iteration
return false;
}
}
}
Note that you need to compare the Strings using equals() method and not the == operator. You also need to handle the corner case of i+1 for the last iteration.
This line
if (components.get(i).getName() == component.getName()) {
Should be
if (components.get(i).getName().equals(component.getName())) {
However, your condition can never happen. If component.get(i-1) is null, then in the previous loop iteration
components.get(i).getName() // <-- null pointer exception, so
component.get(i-1) must not be null and you need to hope that i isn't 0 or you'd get an index out of bounds exception.
Use an iterator
e.g
int i = 0;
Iterator<GuiInterface > it = components.iterator();
while (it.hasNext()) {
i++;
GuiInterface thisComp = it.next ();
if (thisComp.getName().equals(component.getName())) {
if(i > 0 && components.get(i- 1) == null){ // this code does not make sense
return false;
}
}
}
Assuming the passed component is not in your list:
public static boolean isComponentBefore(GUIComponent component) {
// Start at 1 to avoid IndexOutOfBounds
for(int i = 1; i < components.size(); i++) {
if (components.get(i).getName().equals(component.getName())) {
return components.get(i - 1) != null;
}
}
// Given component is not in the list, or the list only has one element
return false;
}
Assuming the passed component is in the list:
public static boolean isComponentBefore(GUIComponent component) {
int index = components.indexOf(component);
return index > 0 && components.get(index - 1) != null;
}

Why is this method to calculate the sum of a binary tree not working?

I know that this code should work but it does not. Does anyone know what i am missing? I am trying to get the sum of all nodes in a binary tree.
public int getSum() {
if (this == null) {
return 0;
} else {
return this.value + right.getSum() + left.getSum();
}
}
Your check this == null is completely useless. However, you do need to be checking for the existence of your left and right nodes. Try this:
return this.value + (right != null ? right.getSum() : 0)
+ (left != null ? left.getSum() : 0);

Counting nodes in a tree in Java

First of all, I swear this is not homework, it's a question I was asked in an interview. I think I made a mess of it (though I did realise the solution requires recursion). Here is the question:
Implement the count() method which returns the number of nodes in a tree. If a node doesn't have either a left or right child, the relevant getXXChild() method will return null
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
// Implement me
}
}
My reason for asking the question is simply curious to see the correct solution, and thereby measure how bad mine was.
Cheers,
Tony
int count() {
Tree right = getRightChild();
Tree left = getLeftChild();
int c = 1; // count yourself!
if ( right != null ) c += right.count(); // count sub trees
if ( left != null ) c += left.count(); // ..
return c;
}
A trivial recursive solution:
int count() {
Tree l = getLeftTree();
Tree r = getRightTree();
return 1 + (l != null ? l.count() : 0) + (r != null ? r.count() : 0);
}
A less trivial non-recursive one:
int count() {
Stack<Tree> s = new Stack<Tree>();
s.push(this);
int cnt = 0;
while (!s.empty()) {
Tree t = s.pop();
cnt++;
Tree ch = getLeftTree();
if (ch != null) s.push(ch);
ch = getRightTree();
if (ch != null) s.push(ch);
}
return cnt;
}
The latter is probably slightly more memory-efficient, because it replaces recursion with a stack and an iteration. It's also probably faster, but its hard to tell without measurements. A key difference is that the recursive solution uses the stack, while the non-recursive solution uses the heap to store the nodes.
Edit: Here's a variant of the iterative solution, which uses the stack less heavily:
int count() {
Tree t = this;
Stack<Tree> s = new Stack<Tree>();
int cnt = 0;
do {
cnt++;
Tree l = t.getLeftTree();
Tree r = t.getRightTree();
if (l != null) {
t = l;
if (r != null) s.push(r);
} else if (r != null) {
t = r;
} else {
t = s.empty() ? null : s.pop();
}
} while (t != null);
return cnt;
}
Whether you need a more efficient or a more elegant solution naturally depends on the size of your trees and on how often you intend to use this routine. Rembemer what Hoare said: "premature optimization is the root of all evil."
I like this better because it reads:
return count for left + count for rigth + 1
int count() {
return countFor( getLeftChild() ) + countFor( getRightChild() ) + 1;
}
private int countFor( Tree tree ) {
return tree == null ? 0 : tree.count();
}
A little more towards literate programming.
BTW, I don't like the getter/setter convention that is so commonly used on Java, I think a using leftChild() instead would be better:
return countFor( leftChild() ) + countFor( rightChild() ) + 1;
Just like Hoshua Bloch explains here http://www.youtube.com/watch?v=aAb7hSCtvGw at min. 32:03
If you get it rigth your code reads...
BUT, I have to admit the get/set convention is now almost part of the language. :)
For many other parts, following this strategy creates self documenting code, which is something good.
Tony: I wonder, what was your answer in the interview.
return (getRightChild() == null ? 0 : getRightChild.count()) + (getLeftChild() == null ? 0 : getLeftChild.count()) + 1;
Or something like that.
Something like this should work:
int count()
{
int left = getLeftChild() == null ? 0 : getLeftChild().count();
int right = getRightChild() == null ? 0 : getRightCHild().count();
return left + right + 1;
}
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
return 1
+ getRightChild() == null? 0 : getRightChild().count()
+ getLeftChild() == null? 0 : getLeftChild().count();
}
}
You can count the tree by traversing it many ways. Simply preorder traversal, the code would be (based on the functions you defined):
int count() {
count = 1;
if (this.getLeftChild() != null)
count += this.getLeftChild().count();
if (this.getRightChild() != null)
count += this.getRightChild().count();
return count;
}
Implement the method:
public static int countOneChild(Node root)
{
...
}
that counts the number of internal nodes in a binary tree having one child. Add the function to tree.java program.
I did it by preorder recurssion. Altough it doesn't exactly follow the interview format by using localRoot, but I think you get the idea.
private int countNodes(Node<E> localRoot, int count) {
if (localRoot == null)
return count;
count++; // Visit root
count = countNodes(localRoot.left, count); // Preorder-traverse (left)
count = countNodes(localRoot.right, count); // Preorder-traverse (right)
return count;
}
public int countNodes() {
return countNodes(root, 0);
}
This is a standard recursion problem:
count():
cnt = 1 // this node
if (haveRight) cnt += right.count
if (haveLeft) cnt += left.count
return cnt;
Very inefficient, and a killer if the tree is very deep, but that's recursion for ya...
int count()
{
int retval = 1;
if(null != getRightChild()) retval+=getRightChild().count();
if(null != getLeftChild()) retval+=getLeftChild().count();
return retval;
}
God I hope I didn't make a mistake.
EDIT: I did actually.
Of course, if you want to avoid visiting every node in your tree when you count, and processing time is worth more to you than memory, you can cheat by creating your counts as you build your tree.
Have an int count in each node,
initialized to one, which
respresents the number of nodes in
the subtree rooted in that node.
When you insert a node, before
returning from your recursive insert
routine, increment the count at the
current node.
i.e.
public void insert(Node root, Node newNode) {
if (newNode.compareTo(root) > 1) {
if (root.right != null)
insert(root.right, newNode);
else
root.right = newNode;
} else {
if (root.left != null)
insert(root.left, newNode);
else
root.left = newNode;
}
root.count++;
}
Then getting the count from any point just involves a lookup of node.count
My first attempt didn't have anything new to add, but then I started to wonder about recursion depth and whether it would be possible to rearrange the code to take advantage of the tail call optimization feature of the latest Java compiler. The main problem was the null test - which can be solved using a NullObject. I'm not sure if TCO can deal with both recursive calls, but it should at least optimize the last one.
static class NullNode extends Tree {
private static final Tree s_instance = new NullNode();
static Tree instance() {
return s_instance;
}
#Override
Tree getRightChild() {
return null;
}
#Override
Tree getLeftChild() {
return null;
}
int count() {
return 0;
}
}
int count() {
Tree right = getRightChild();
Tree left = getLeftChild();
if ( right == null ) { right = NullNode.instance(); }
if ( left == null ) { left = NullNode.instance(); }
return 1 + right.count() + left.count();
}
The precise implementation of NullNode depends on the implementations used in Tree - if Tree uses NullNode instead of null, then perhaps the child access methods should throw NullPointerException instead of returning null. Anyway, the main idea is to use a NullObject in order to try to benifit from TCO.
Questions related to binary tree should be expected in an interview. I would say to take time before any next interview and go through this link. There are about 14 problems solved .You can have a look and how the solution is done. This would give you an idea of how to tackle a problem with binary tree in future.
I know your question is specific to the count method .That is also implemented in the link that i provided
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
if(this.getLeftChild() !=null && this.getRightChild()!=null)
return 1 + this.getLeftChild().count() + this.getRightChild().count();
elseif(this.getLeftChild() !=null && this.getRightChild()==null)
return 1 + this.getLeftChild().count();
elseif(this.getLeftChild() ==null && this.getRightChild()!=null)
return 1 + this.getRightChild().count();
else return 1;//left & right sub trees are null ==> count the root node
}
}

Categories