I'm working on a problem for class I'm stuck on. It involves adding a methods to the Binary Search Tree found here: http://algs4.cs.princeton.edu/32bst/BST.java.html
I need to develop an iterative ceiling method that finds the ceiling for a given key. It cannot be recursive.
Here is my code so far. I understand the basics of the algorithm I am supposed to implement, but I'm finding actually doing so hard to wrap my head around.
Thanks in advance for any help you might be able to offer.
public Key ceiling_i(Key key)
{
Node t = root;
for(int i = 0; i < size(); i++){
int cmp = key.compareTo(t.key);
if(cmp == 0) return t.key;
else if(cmp < 0) t = t.left;
else if(cmp > 0) t = t.right;
}
return null;
}
Edit: The main problem I am having is how to deal with the iterations after the first one. According to my book, "If a given key is greater than the key at the root of a BST,
then the ceiling of key (the largest key in the BST greater
than or equal to key) must be in the right subtree. If key is
less than the key at the root, then the ceiling of key could
be in the left subtree; if not (or if key is equal to the key
at the root), then the key at the root is the ceiling of key." I am not sure how to deal with that in the loop.
Your code is a good start. But your for loop does not make sense to me.
public Key ceiling_i(Key key)
{
Node t = root;
Node t largestVisited = null;
while(t != null) {
int cmp = key.compareTo(t.key);
if(cmp == 0) return t.key;
else if(cmp < 0) { largestVisited = Min(t, largestVisited); t = t.left; }
else if(cmp > 0) { t = t.right; largestVisited = Min(t, largestVisited); }
}
return largestVisited;
}
Node Min(Node a, Node b) { return the node with the smaller key; }
Tip: You could have derived this code by first writing the recursive solution and noticing that it is tail recursive. Tail recursive functions can trivially made non-recursive by just reusing the already existing local variables. No need to open another stack-frame if you won't ever use the old one again.
The code from that book is NOT tail-recursive because the first ceiling() call has operations done on it before the returns.
private Node ceiling(Node x, Key key) {
if (x == null) return null;
int cmp = key.compareTo(x.key);
if (cmp == 0) return x;
if (cmp < 0) {
Node t = ceiling(x.left, key);
if (t != null) return t;
else return x;
}
return ceiling(x.right, key);
}
Change ceilng() so the recursive calls are an "accumulator" type of tail-call. Do this by passing additional parameters which hold the work done so far.
Null or a node is passed as x.left when cmp < 0. What has "accumulated" so far is a larger-than-item node x found at this conditional test.
In the original version after the the first recursive call, t is either null or some tree node. Node x is then used after if t is null. In a modified version an additional parameter will be passed the x node.
In the other conditional test of cmp > 0 with the tail call, there is no new "accumulated" work since x is smaller than the item and is not used in deciding a return value if x.right is null.
Notice what happens if we pass an "accumulated x" to "larger" in a modified ceiling(x, key, larger) function. In this modified function, the condition "if (x == null) return null" is replaced by "if (x == null) return larger" and all the t-value evaluations are removed after the first recursive call. With the second tail-call just pass null to larger.
So the conversion should look something like this:
private Node ceiling (Node x, Key key, Node larger) {
if (x == null) return larger;
int cmp = key.compareTo(x.key);
if (cmp == 0) return x;
if (cmp < 0) {
return ceiling(x.left, key, x);
}
return ceiling(x.right, key, null);
}
Now the function is tail-recursive and can be further converted into an iterative loop form.
private Node ceiling (Node x, Key key) {
Node larger = null;
while (x != null) {
int cmp = key.compareTo(x.key);
if (cmp == 0) return x;
if (cmp < 0) {
larger = x;
x = x.left;
} else {
x = x.right;
}
}
return larger;
}
Related
My Approach is this- I used an arraylist. I checked all the nodes of the Binary Tree, to find those whose left and right node are null, which signifies that they are a leaf, then I found out their levels and added them to an arraylist.
After this I used the Arraylist in the function boolean check to check whether all the elements of the array list are same of not, if they are i return true (all leaves are at the same level) otherwise I return false.
class Solution {
boolean check(Node root) {
int c = 0;
ArrayList<Integer> a = new ArrayList<>();
for (int x : a) {
if (x != (a.get(0)))
return false;
}
return true;
}
public void che(Node root, int level, ArrayList<Integer> a) {
if (root == null) return;
if (root.left == null && root.right == null) {
a.add(level);
}
che(root.right, level + 1, a);
che(root.left, level + 1, a);
}
}
This is the link for the Question
The che function is never called.
It is however not necessary to collect data in an array list. Instead make the recursive function return the height of the subtree it is called on. In the same function compare the height that is returned for the left and right subtree. If they are different, return a special value to indicate failure (like -2), otherwise return that common height plus one.
This allows the function to abort the search as soon as a height difference is found, avoiding the unnecessary traversal of the rest of the tree.
Here is how that would look:
class Solution
{
boolean check(Node root) {
return height(root) > -2;
}
private int height(Node root) {
if (root == null) return -1;
int left = height(root.left);
if (left == -2) return -2;
int right = height(root.right);
if (left == -1 || right == -1 || left == right) {
return 1 + Math.max(left, right);
}
return -2;
}
}
I am trying this problem on Practice-It, but have been having trouble with it for quite a while.
Write a method matches that returns a count of the number of nodes in one tree that match nodes in another tree. A match is defined as a pair of nodes that are in the same position in the two trees relative to their overall root and that store the same data.
So far, I've tried the following below, but I don't quite get the count I want, and I'm not quite sure why.
public int matches(IntTree t2)
{
return match(overallRoot, t2.overallRoot);
}
public int match(IntTreeNode tree1, IntTreeNode tree2)
{
if(tree1 == null && tree2 == null)
return 1;
if(tree1 == null || tree2 == null)
return 0;
if(tree1.data == tree2.data)
return 1;
int left = match(tree1.left, tree2.left);
int right = match(tree1.right, tree2.right);
return left + right;
}
Any help would really be appreciated!
You're stopping your search if the current node matches. If it's different, you check left and right, but on a match you return one.
You are very close to the solution, you have to consider:
if one of the nodes is null you can stop the visit for the subtrees and return 0
if the data for the two roots are different the count is 0 otherwise is 1 and after you can calculate the count for the two subtrees adding to the count for the two roots.
Below my suggestions as code:
public int match(IntTreeNode tree1, IntTreeNode tree2) {
if(tree1 == null || tree2 == null) { return 0; }
int count = tree1.data == tree2.data ? 1 : 0;
int left = match(tree1.left, tree2.left);
int right = match(tree1.right, tree2.right);
return count + left + right;
}
Full answer for the practice it one:
int matches(IntTree tree2) {
return matches(tree2.overallRoot, this.overallRoot);
}
int matches(IntTreeNode tree1, IntTreeNode node2)
{
int left=0, right=0, count =0;
if(tree1 == null && this != null || this == null && tree1 != null) { return 0; }
count = tree1.data == node2.data ? 1 : 0;
if(tree1.left != null && node2.left !=null){
left = matches(tree1.left, node2.left);}
if(tree1.right != null && node2.right !=null){
right = matches(tree1.right, node2.right);}
return count + left + right;
}
I'm trying to figure out the minimum depth to a leaf node using breadth first search. I have the following basic structure
public int BFS(Node root){
if (root == null) return 0;
Queue<Node> q = new LinkedList<Node>();
int min = 1;
q.clear(); // I saw this in a queue example, unsure if needed
q.add(root);
while (! q.isEmpty()){
Node n = q.remove();
if (n.left != null) q.add(n.left);
if (n.right != null) q.add(n.right);
}
}
I'm not sure where to update the min height counter. I had thought about placing it inside the if statements as temp loop variables l & r where I would set them to 1 if the left or right is not null, 0 else. Then add the min of these 2 to the min height but this only works if I'm at one level above the leafs.
The idea should be something like:
First node added to the queue should have distance = 1.
For new nodes added to the queue: distance = actual node distance + 1
When you find a leaf, you return actual node distance. END.
In pseudocode:
root.depth := 1
q := create queue
q.add(root)
while q is not empty
Node n := q.dequeue()
if (n is leaf) then
return n.depth
if (n.left is not null) then
n.left.depth := n.depth + 1
q.add(n.left)
if (n.right is not null) then
n.right.depth := n.depth + 1
q.add(n.right)
return 0
You could use a queue of pairs (node, depth). Since the search is BFT, the first leaf contains the minimum depth.
Based on your code, the algorithm would be something like that (pseudo java code):
public int BFS(Node root)
{
if (root == null)
return 0;
Queue<Pair<Node,int>> q = new LinkedList<Pair<Node,int>>();
q.add(new Pair(root, 0));
while (! q.isEmpty()) {
Pair p = q.remove();
Node n = p.getFirst();
if (n.left == null && n.right == null) // is this a leaf?
return p.getSecond(); // yes! ==> p.getSecond() is its min depth
if (n.left != null)
q.add(new Pair(n.left, p.getSecond() + 1));
if (n.right != null)
q.add(new Pair(n.right, p.getSecond() + 1));
}
}
Of course, you need the Pair class, but I leave to you these details
Generally in BFS, your nodes have a distance field. the roots distance is zero, then whenever you add a new node to the queue, you set its distance to n.distance+1
According to API the ceiling should return number greater then or equal to the given element or null, in the code below why ceiling of -12 is -12?
NavigableSet<Integer> sset = new TreeSet<>();
sset.add(-12);
sset.add(-13);
sset.add(-11);
sset.add(24);
//why the ceiling of -12 is -12? there are number greater then -12 in the set
System.out.println(sset.ceiling(-12));
System.out.println(sset.ceiling(0));
System.out.println(sset.ceiling(24));
System.out.println(sset.ceiling(100));
Quoting the documentation link you mentionned:
Returns the least element in this set greater than or equal to the
given element, or null if there is no such element.
Note that it is a Sorted TREE and the method returns least element in this set greater than or equal to the given element
Try to understand this method which actually returns you the ceiling.
final Entry<K,V> getCeilingEntry(K key) {
Entry<K,V> p = root;
while (p != null) {
int cmp = compare(key, p.key);
if (cmp < 0) {
if (p.left != null)
p = p.left;
else
return p;
} else if (cmp > 0) {
if (p.right != null) {
p = p.right;
} else {
Entry<K,V> parent = p.parent;
Entry<K,V> ch = p;
while (parent != null && ch == parent.right) {
ch = parent;
parent = parent.parent;
}
return parent;
}
} else
return p;
}
return null;
}
The following will return you -11 and -13 as they are least about greater than or equal to the given element.
System.out.println(sset.ceiling(-11));
System.out.println(sset.ceiling(-13));
I'm having a hard time understanding this code for the ranking of nodes by size. Rank returns the size of all the nodes less than the key.
http://algs4.cs.princeton.edu/32bst/BST.java.html
how is the result returned for rank(key, x.left)???
code:
public int rank(Key key) {
return rank(key, root);
}
// Number of keys in the subtree less than key.
private int rank(Key key, Node x) {
if (x == null) return 0;
int cmp = key.compareTo(x.key);
if (cmp < 0) return rank(key, x.left);
else if (cmp > 0) return 1 + size(x.left) + rank(key, x.right);
else return size(x.left);
}
// is the symbol table empty?
public boolean isEmpty() {
return size() == 0;
}
// return number of key-value pairs in BST
public int size() {
return size(root);
}
// return number of key-value pairs in BST rooted at x
private int size(Node x) {
if (x == null) return 0;
else return x.N;
}
Note that rank does not return an entry (a node value) but rather a value that represents the comparison between given Key and that of the candidate Node's left subtree (the left-most value for a node in a binary search tree).
The value it returns stems from an implementation of the standard Comparable interface: negative integer if first element is lesser than second, positive if it is greater, 0 if they are equal.
In this particular case, the exact number returned indicates the distance (difference) between both keys being compared, which might be useful for the code using the comparison result--usually, sort algorithms.