I would like to test if two given BSTs (Binary Search Trees) are equal in Java. The BST nodes do not have pointers to the parent nodes.
The simplest solution is to traverse both BSTs, create two traversal lists and test if the lists are equal. However it requires O(N) memory.
I would like to try another way: create an Iterator, which traverses the BSTs, and ... the rest is obvious.
Does it make sense? Is there any "better" (simpler and efficient) solution to test if two BSTs are equal?
Binary search tree is a tree, right?
Two trees are equal if they have the same root and the same children.
Each child is also a tree.
See point 2.
Hint: recursion. The memory consumption is O(logn) (prove it yourself).
Implement a recursive equals() method. It would require no memory, and would be easy to code.
Something like this should work:
public class Node {
Object value;
private Node left;
private Node right;
public boolean equals(Object o) {
if (o instanceof Node) {
Node node = (Node)o;
if (value.equals(node.value)) {
return true;
}
return ((left == null && node.left == null) || left.equals( node.left)) &&
((right == null && node.right == null) || right.equals( node.right));
}
return false;
}
}
Note that you should override hashCode() to reflect this implementation, so consider naming the above impl as equalsDeep() instead and skipping the hashCode() impl.
The easiest way could be, create a hash of both tree and then check whether they are equal or not. This only apply if the content of both tree are same as well.
How to create checksum and then compare those checksum.
http://www.mkyong.com/java/how-to-generate-a-file-checksum-value-in-java/
Related
I'm trying to compare series of two binary trees and seeing if they have the same elements in them but the trees can have different structures all recursively.
Here is my current code, the "Find" function is a search the tree function:
private static boolean problem1Recursive(Node t1, Node t2)
{
if(t1 == null || t2 == null)
{
return false;
}
else if(find(t2, t1.key))
{
return true;
}
return (problem1Recursive(t1.left, t2) && problem1Recursive(t1.right, t2));
}
I'm just at a loss on where to go from here
The code you provided seems to be checking if all elements in the first tree exist in the second tree, rather than checking if the two trees have the same elements. But, in your problem statement you have stated that the trees can have different structures and you want to compare if they have the same elements.
Here is one possible solution to your problem:
private static boolean problem1Recursive(Node t1, Node t2) {
if (t1 == null && t2 == null) {
return true;
}
if (t1 == null || t2 == null) {
return false;
}
if (t1.key != t2.key) {
return false;
}
return problem1Recursive(t1.left, t2) || problem1Recursive(t1.right, t2);
}
This function first check if both nodes are null, if they are it returns true. If one of the nodes is null it returns false, indicating that the trees have different elements. If the key of the nodes is different it also returns false. It then recursively checks the left and right subtrees of the first tree against the entire second tree. If at least one of the subtrees contains all the elements of the second tree, the function will return true.
It's important to note that this solution considers that there aren't repeating values on the tree and the values are comparable.
I am having problems trying to check if a value is in a linked list or not using recursion. The values in the linked list are between 0 and 5. If the value is in the linked list, the method should return true. However, I am getting wild answers across the board if the value is indeed in the linked list. Some numbers will return false, and some will return true. I am not sure why it is doing this. Thanks!
public boolean contains(int aData)
{
Node currentNode = firstNode;
if(currentNode == null) {
return false;
}
if(currentNode.data == aData) {
return true;
}
else {
return false;
}
}
You're only checking one node (the first node). You're going to be needing something like this:
public boolean contains(int aData, Node node)
{
Node currentNode = node;
// base case; if this node is null, return false
if(currentNode == null) {
return false;
}
// if this node contains the data, return true, otherwise, check next nodes.
if(currentNode.data == aData) {
return true;
} else {
return contains(aData, currentNode.next);
}
}
You can call the above function starting with the head node
contains(5, headNode);
and it will run through your entire list until either a) it finds the data, or b) it has exhausted all options and the data was not found.
As has been mentioned, you are not using recursion and are only checking the first Node. If you want to use recursion, you'll need to call the contains method from within the contains method, which you are not currently doing. Even if you were to simply call it at the end of the method as it stands now, it still wouldn't do anything - think about how you might rewrite it if the method started:
public boolean contains(int aData, Node nodeToCheck)
Recursion has a very well defined form that is used in almost all cases. Essentially the form is:
type method(context) {
if (one of the base cases holds)
return appropriate base value
else
for each possible simpler context
return method(simpler context);
}
This works by progressively breaking the problem down into smaller pieces until the problem is so simple it has an obvious answer (i.e. the base case). The key to using recursion is to ask yourself 'in what situations is the answer obvious?' (i.e. the base cases) and 'when the answer isn't obvious how can I simplify the situation to make it more obvious?'. Don't start coding until you can answer those questions!
In your case you have 2 base cases: you've reached the end of your list or you have found the value. If neither of those cases hold then try again in a simpler context. In your case there's only one simpler context: a shorter list.
Putting all that together you have:
public boolean contains(Node node, int data) {
if (node == null)
return false;
else if (node.value == data)
return true;
else
return contains(node.next, data);
}
I was trying to solve the problem 4.7 from the book cracking the code interview (very cool book!).
Design an algorithm and write code to find the first common ancestor
of two nodes in a binary tree. Avoid storing additional nodes in a
data structure. NOTE: This is not necessarily a binary search tree.
And I came up with this solution which is not even close to the ones provided in the book. I wonder if someone can find any flaws on it?
Solution:
I created a wraper class to hold the first common ancestor (if its found) and 2 booleans to track if a or b was found when recoursively searching the tree. Please read added comments in the code below.
public static void main (String args[]){
NodeTree a, b, head, result; //initialise and fill with data
fillTreeTestData(head);
pickRandomNode(a);
pickRandomNode(b);
result = commonAnsestor(a,b,head);
if(result != null)
System.out.println("First common ansestor "+result);
else
System.out.println("Not found");
}
class TreeNode{
Object value;
TreeNode right, left;
}
class WraperNodeTree{
boolean found_a;
boolean found_b;
NodeTree n;
WraperNodeTree (boolean a, boolean b, NodeTree n){
this.n = n;
this.a = a;
this.b = b;
}
}
static WraperNodeTree commonAnsestor(NodeTree a, NodeTree b, NodeTree current){
// Let's prepare a wraper object
WraperNodeTree wraper = new WraperNodeTree(false, false, null);
// we reached the end
if(current == null) return wraper;
// let's check if current node is either a or b
if(a != null)
wraper.found_a = current.value.equals(a.value);
else if(b != null)
wraper.found_b = current.value.equals(b.value);
else
return wraper; // if both are null we don't need to keep searching recoursively
// if either a or b was found let's stop searching for it for performance
NodeTree to_search_a = wraper.found_a ? null : a;
NodeTree to_search_b = wraper.found_b ? null : b;
// let's search the left
WraperNodeTree wraperLeft = common(to_search_a,to_search_b,current.left);
// if we already have a common ancester just pass it back recoursively
if(wraperLeft.n != null) return wraperLeft;
WraperNodeTree wraperRight = common(to_search_a,to_search_b,current.right);
if(wraperRight.n != null)return wraperRight;
// keep the wraper up to date with what we found so far
wraper.a = wraper.found_a || wraperLeft.found_a || wraperRight.found_a;
wraper.b = wraper.found_b || wraperLeft.found_b || wraperRight.found_b;
// if both a and b were found, let's pass the current node as solution
if(wraper.found_a && wraper.found_b)
wraper.n = current;
return wraper;
}
If it's about finding flaws:
Flaw #1:
I think there are too many typos in your code, which may confuse the interviewer on their first read of the code (and you don't want that!). For example, you write 'NodeTree' and 'TreeNode' interchangeably. Also, you define 'commonAncestor()' and then call 'common()'. Those things make the interviewer confused and make him drift apart from the important thing, which is understanding your way of solving the problem.
Flaw #2: Typos aside, I think another flaw is that this code is difficult to follow. I think one of the reasons is because you have 'return' statements all over the body of your function (at the beginning, at the middle and at the end). This should 'normally' be avoided in favor of readability.
Usually my approach is to organize the code in the following way:
Basic border case checks (which might include return)
Main body of the function (which should NOT return under any conditions)
Last checks and final RETURN
But when you have return statements in the middle, it makes it harder for the reader to imagine the flow.
Flaw #3: I think you're trying to solve two problems with the same function (commonAncestor). You are trying to both search for 'a' and 'b' and also keeping track of the common ancestor. I think if this is an interview question, you could separate those two objectives in favor of simplicity.
For example, consider this code (might not be perfect and need some extra border checks):
/**
* [Assumption]: If we call firstCommonAncestor(a, b, root)
* we TRUST that root contains both a and b.
*
* You can (and should) discuss this
* assumption with your interviewer.
*/
public static Node firstCommonAncestor(Node a, Node b, Node root) {
// If root matches any of the nodes (a or b),
// then root is the first common ancestor
// (because of our assumption)
if(root == a || root == b) return root;
// Search for a and b in both sides
SearchResult leftResult = searchNodes(a, b, root.left);
SearchResult rightResult = searchNodes(a, b, root.right);
// If a and b are on the same side (left or right), then we
// call firstCommonAncestor on that side and that’s it
if(leftResult.aFound && leftResult.bFound)
return firstCommonAncestor(a, b, root.left);
else if(rightResult.aFound && rightResult.bFound)
return firstCommonAncestor(a, b, root.right);
else {
// If a and b are in different sides,
// then we just found the first common ancestor
return root;
}
}
class SearchResult {
boolean aFound, bFound;
}
On the code above, I'm separating the task of actually searching for 'a' and 'b' in a different function called searchNodes, which is fairly easy to implement if your interviewer asks for it. But he might not even do that. And if he does, at that point he already understood your approach, so it's easier now to "make the code a bit more complicated" without confusing the interviewer.
I hope this helps.
I have two trees. The tree Node is defined as
class Node{
String treeId;
String type; //Each node has type which has fixed value. For example, its color: RED, BLANK, GREEN
Set<Node> children;
String ref; //The ref is a string and allowed value are "0", "1",..."10". The value is null if it is not leaf.
};
For leaf, the children set is empty.
I am wondering whether there is some existing efficient work done how to identify equivalent substree for two given tree. The equivalent is defined as:
1) Both subtree leaves are setsets leaves of original tree.
2) Both subtrees leaves have same ref value.
3) for non-leaves node, the equivalent refers to both node have same type and equivalent children.
Thanks. It would be better if there is some Java library addressing this problem.
The input should are two tree roots while output is the Node that is root of equivalent subtree. An the the tree's height is 100~ and it has more than 500 nodes.
What i did now is that I added a new field for class Node.
class Cache{
Map<String, Set<String>> map = new LinkedHashMap<String, Set<Str>>();
}
The key of map is Node id while the value is a ref set this node of this nodeid can reach. The Cache initiated when Node is initialized.
During isEquivalent compare phase, check whether overlap exists between two root's ref set. Return false if none.
I think this can help reduce the number of comparison space.
I am not sure about 1) Both subtree leaves are leaves of original tree. requirement as it seems to conflict with how to identify equivalent substree for two given tree.. Otherwise following recursive method should be able to cover other two conditions. The haveSameOriginalTree(r1, r2) method may be implemented to satisfy the first condition that I couldn't understand. r1 and r2 are roots of two subtrees that need to be checked for equivalence.
bool areEquivalent(Node r1, Node r2)
{
if(r1.children == null && r2.children == null)
{
return (haveSameOriginalTree(r1, r2) && (r1.ref == r2.ref));
}
if((r1.children == null && r2.children != null) || (r1.children != null && r2.children == null))
{
return false;
}
// if here then both must be non-leaf nodes
if(r1.type != r2.type)
{
return false;
}
if(r1.children.getCount() != r2.children.getCount()) // not sure of correct syntax for Java Sets
{
return false;
}
for(int i=0; i<r1.children.getCount(); i++)
{
if(!areEquivalent(r1.children[i], r2.children[i])) // again please correct the syntax for Sets
{
return false;
}
}
return true;
}
Let me know what you think.
Update
Here is an iterative version of the above solution. It uses stack data structure which is allocated on the heap rather than pushed on function's call stack, so not hugely different from recursive but still better. Also, since we only hold references to Nodes (rather than copying the whole object), this shouldn't be that much of an additional memory overhead if we are already loading the original tree into memory.
bool areEquivalent(Node r1, Node r2)
{
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>();
Node n1, n2;
s1.Push(r1);
s2.Push(r2);
while(true) // Need a better check
{
if(s1.getCount() != s2.getCount())
{
return false;
}
if(s1.getCount() == 0) // if both stacks are empty then we've traversed both trees without failure.
{
return true;
}
n1 = s1.Pop();
n2 = s2.Pop();
if(!areEquivalentNodes(n1, n2))
{
return false;
}
foreach(Node child in n1.children)
{
s1.Push(child);
}
foreach(Node child in n2.children)
{
s2.Push(child);
}
}
}
// only checks the two nodes are equivalent. their childrens' equivalence will be handled by other calls to this method.
bool areEquivalentNodes(Node n1, Node n2)
{
if(n1.children.getCount() != n2.children.getCount())
{
return false;
}
if(n1.children.getCount() == 0) // if both are leaf nodes...
{
if(n1.ref != n2.ref)
{
return false;
}
}
else // both are non-leaf
{
if(n1.type != n2.type)
{
return false;
}
// the condition that children of non-leaf nodes be equivalent will be covered by subsequent calls this method...
}
return true;
}
Please note that both solutions expect children of two equivalent nodes in the same order. If children are not ordered then we will need to sort them before calling above code.
Let me know if this is better.
Anyone could help me do this: I need a public method for my binary search tree ADT that returns a reference to the information in the node with the smallest value in the tree. The signature of the method is:
public T min()
A. Design an interative version of the method.
B. Design a reccursive version of the method.
C. Which approach is better? Explain please.
This is not a HW or anything, its a practice for myself.
As i think that if i gave you the solution you will not learn, i'll give a link to you read more about Binary Search Tree: http://en.wikipedia.org/wiki/Binary_search_tree
After that comment, My way:
public T min() {
return recMin(root).getInfo();
}
public BSTnode<T> recMin(BSTnode<T> tree) {
if (tree == null) {
throw new NoSuchElementException();
}
if (tree.left == null) {
return tree;
}
return recMin(tree.left);
}
public T IterationMin(BSTnode<T> tree) {
if (tree == null) {
throw new NoSuchElementException();
}
while (tree.left != null) {
tree = tree.left;
}
return tree.getInfo();
}
On the matter of whether iterative or recursive is better. It really depends. In general recursive solutions tend to be easier to understand, but slower since they consume more and more stack space proportional to the depth of recursion. In this case however, you can come up with a tail-recursive solution which should be easy to understand and just as efficient as the iterative solution.
public BSTNode<T> findMin(BSTNode<T> node) {
if (node.left == null) // if there is no left, we are done
return node;
return findMin(node.left); // recursively search on the left-child
}
Start by calling this method on the head node.
A binary search tree has a lower value to the left always, correct? So, you should always go left when you can. If you can't, then you've reached the lowest value.