This is the most common implementation for binary tree height I have found on internet
public int height(BinaryNode t) {
if (t == null) {
return 0;
} else {
return 1 + Math.max(height(t.left), height(t.right));
}
}
But shouldn't it modified like this since it is adding an unnecessary 1 at leaf nodes
public int height(BinaryNode t) {
if (t == null) {
return 0;
} else if (t.left == null && t.right == null) {
return 0;
} else {
return 1 + Math.max(height(t.left), height(t.right));
}
}
Related
I am trying to implement a getHeight method that has a o(1) time complexity. To do this I am aiming to assign every node their own height and to return the height of the root with the getHeight method. To do this I need to update the height of the nodes everytime I add or remove.
Thus, I chose to do this:
private void updateHeight(Node node)
{
if (node == null)
{
return;
}
updateHeight(node.left);
updateHeight(node.right);
this.helpHeight(node);
}
private void helpHeight(Node node)
{
if (this.isLeaf(node))
{
node.height = 0;
}
else if (node.left == null)
{
node.height = node.right.height + 1;
}
else if (node.right == null)
{
node.height = node.left.height + 1;
}
else
{
node.height = 1 + max(node.left.height, node.right.height);
}
}
private int max(int height, int height2) {
if (height > height2)
{
return height;
}
else
{
return height2;
}
}
public int height()
{
return root.height + 1;
}
Then I will call the updateHeight(Node node) method with the root as the parameter. However, it's not working when I test it this way:
public static void main(String[] arg)
{
BST bst = new BST();
bst.add("a");
bst.add("b");
bst.add("c");
System.out.println(bst.height());
bst.remove("c");
System.out.println(bst.height());
}
It's returning 2, then 2.
Just in case, here is my add method:
public boolean add(E e) throws NullPointerException
{
if (e == null)
{
throw new NullPointerException("Error: Cannot add a null object to the tree.");
}
if (root == null)
{
root = new Node(e);
return true;
}
Node current = root;
while (current != null ) {
if (current.data.compareTo(e) > 0) {
//add in the left subtree
if (current.left == null ) {
current.left = new Node (e);
size++;
this.updateHeight(root);
return true;
}
else {
current = current.left;
}
}
else if (current.data.compareTo(e) < 0) {
//add in the right subtree
if (current.right == null ) {
size++;
this.updateHeight(root);
current.right = new Node(e);
return true;
}
else {
current = current.right;
}
}
else { //duplicate
return false;
}
}
//should never get to this line
return false;
}
I know there many similar questions and I have received big help by reading answers to those questions, however I am not able to see how is my client facing this problem. And there is only one client who is facing this problem.
I have a List, and I am sorting that list using Comparator interface. Does any of you see problem with the following code?
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
#Override
public int compare(BiologySample left, BiologySample right) {
if (left == right || (left != null && right != null && left.getSampleDateTime() == right.getSampleDateTime())) {
return 0;
}
if (left == null || left.getSampleDateTime() == null) {
return 1;
}
if (right == null || right.getSampleDateTime() == null) {
return -1;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
And this how I am calling this function
Collections.sort(biologySamples, new BiologySamplesComparator());
I know that the main problem in this kind of scenario is Transitivity. However I couldn't figure what is violating that rule.
This how getSampleDateTime() is returning date Fri Apr 09 17:00:00 PDT 2021
Update
This is how I was able to fix my problem.
I hope this helps, I was stuck for so long on this problem.
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
#Override
public int compare(BiologySample left, BiologySample right) {
if (left == null) {
if (right == null) {
return 0;
} else {
return 1;
}
} else if (right == null) {
return -1;
} else if (left == right) {
return 0;
}
if (left.getSampleDateTime() == null) {
if (right.getSampleDateTime() == null) {
return 0;
} else {
return 1;
}
} else if (right.getSampleDateTime() == null) {
return -1;
} else if (left.getSampleDateTime() == right.getSampleDateTime()) {
return 0;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
You have a possible inconsistency when comparing a null "sample" to a non-null sample with a null timestamp.
Sample a = null;
Sample b = new Sample(null);
bsc.compare(a, b); // -> 1, a > b
bsc.compare(b, a); // -> 1, b > a
First, you should replace the Date in your sample class with Instant if at all possible, and then make your life simpler by saying this:
public static final Comparator<Sample> ORDER_BY_TIMESTAMP =
Comparator.nullsLast(Comparator.comparing(
Sample::getDateTime,
Comparator.nullsLast(Comparator.naturalOrder())
);
If you can rule out null values, even simpler:
Comparator.comparing(Sample::getDateTime);
I was missing some conditional for some cases and this is how I was able to solve my problem.
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
#Override
public int compare(BiologySample left, BiologySample right) {
if (left == null) {
if (right == null) {
return 0;
} else {
return 1;
}
} else if (right == null) {
return -1;
} else if (left == right) {
return 0;
}
if (left.getSampleDateTime() == null) {
if (right.getSampleDateTime() == null) {
return 0;
} else {
return 1;
}
} else if (right.getSampleDateTime() == null) {
return -1;
} else if (left.getSampleDateTime() == right.getSampleDateTime()) {
return 0;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
courtesy of Why does my compare methd throw IllegalArgumentException sometimes?
Basically I don't know why my integer n doesn't get higher.
Thanks for every answer!
public int n;
public int firstIndexOf(T val) {
if (val == this.getValue()) {
return n;
} else {
if (val != this.getValue() && this.next != null) {
n++;
return this.next.firstIndexOf(val);
} else {
return -1;
}
}
}
The increment (n++) was in the wrong condition check:
private int n = 0;
public int firstIndexOf(int val) {
if ( val == this.getValue() ) {
return n+1; //This is were the increment should happen
}
else {
if ( this.next != null ) {
return this.next.firstIndexOf(val);
} else {
return -1;
}
}
}
Also if you want to count all the elements in your linked list which have the same value as val, you can use this:
private int n = 0;
public int firstIndexOf(int val) {
if ( val == this.getValue() ) {
if ( this.next != null ) {
return 1 + this.next.firstIndexOf(val);
}
else {
return 1;
}
} else {
if ( this.next != null ) {
return this.next.firstIndexOf(val);
} else {
return 0;
}
}
}
How do you count number of branches, in this case branches with even integers. Here's what I have so far. It seems to work for a couple of the cases.
public int evenBranches() {
return evenBranches(overallRoot);
}
private int evenBranches(IntTreeNode root) {
if (root == null) {
return 0;
}
int val = 0;
if (root.left != null) {
val += evenBranches(root.left);
} else if (root.right != null) {
val += evenBranches(root.right);
}
if (root.data % 2 == 0) {
return val + 1;
} else {
return val;
}
}
You can modify the evenBranches() method as below: I think It will cover all edge cases, If any testcase is left, let me know, I will fix it.
public int evenBranches() {
return evenBranches(overallRoot, 0);
}
private int evenBranches(IntTreeNode root, int count) {
if(root == null || (root.left == null && root.right == null)) {
return count;
}
if(root.data % 2 == 0) {
count++;
}
count += evenBranches(root.left, count);
count += evenBranches(root.right, count);
return count;
}
You may need to remove the else condition when checking the occurrences in right branch. Otherwise it will check only one side. eg:
private int evenBranches(IntTreeNode root) {
if (root == null) {
return 0;
}
int val = 0;
if (root.left != null) {
val += evenBranches(root.left);
}
if (root.right != null) {
val += evenBranches(root.right);
}
if (root.data % 2 == 0) {
return val + 1;
} else {
return val;
}
}
You can very well achieve the desired results by using a global variable, and applying BFS (breadth first search) on your tree, in this manner:
int evencount = 0; // global-var.
public int evenBranches() {
evenBranches(overallRoot);
return evencount;
}
private void evenBranches(IntTreeNode root) {
if(!root) return;
if( (root.left || root.right) && (root.data % 2 == 0)){
evencount++;
}
evenBranches(root.left);
evenBranches(root.right);
}
public void insert(int v) {
Node t = root;
int compareResult;
compareResult = 0;
if ((t.getData()).equals(v)) return;
if (t == null) {
Node n = new Node<>(v, t, null, null);
} else
while (t != null) {
compareResult = v.compareTo(t.getData());
if (compareResult > 0) {
if (t.getRight() != null) {
t = t.getRight();
} else {
Node n = t.getRight();
break;
}
}
else {
compareResult = v.compareTo(t.getData());
if (compareResult < 0) {
if (t.getLeft() != null) {
t = t.getLeft();
} else {
Node n = t.getLeft();
break;
}
}
}
}
v is a primitive int. You can't call methods on primitive types in Java.
You can however replace v.compareTo(t.getData()) with Integer.compare(v, t.getData())