From a binary tree, you want to create a 2-d arraylist where each arraylist within the main arraylist contains all the nodes of a binary tree on a single level, for all of the levels. I understand how to do this recursively with DFS but I am very confused about why it possible to get the correct answer by passing in the arraylist I want to populate as a parameter in the recursive function.
The header of my recursive function looks like this
createLevelLinkedList(TreeNode current, ArrayList<LinkedList<TreeNode>> lists, int level)
With basecase:
if (current == null) return;
As the tree is traversed, the current node will be appended to its corresponding arraylist within "lists". Within the recursive function there there two recursive calls to move the function to the child nodes of current:
createLevelLinkedList(current.left, lists, level + 1);
createLevelLinkedList(current.right, lists, level + 1);
Suppose there is a tree that looks like this
5
3 8
2 4 9
With depth first tree traversal, after the first return, we will have TreeNode "2" is the top object in the stack, then "3". When TreeNode "3" is current and the function calls
createLevelLinkedList(current.right, lists, level + 1);
To push TreeNode "4" onto the stack, how can lists contains TreeNode "2" if it actually does and what is really going in memory?
The code I am referencing can be found on Github: https://github.com/gaylemcd/ctci/blob/master/java/Chapter%204/Question4_4/QuestionDFS.java
public static void createLevelLinkedList(TreeNode root, ArrayList<LinkedList<TreeNode>> lists, int level)
{
if (root == null) return;
LinkedList<TreeNode> list = null;
if (lists.size() == level) { // Level not contained in list
list = new LinkedList<TreeNode>();
/* Levels are always traversed in order. So, if this is the first time we've visited level i,
* we must have seen levels 0 through i - 1. We can therefore safely add the level at the end. */
lists.add(list);
} else {
list = lists.get(level);
}
list.add(root);
createLevelLinkedList(root.left, lists, level + 1);
createLevelLinkedList(root.right, lists, level + 1);
}
You should understand that there's only one ArrayList instance passed to the createLevelLinkedList method. Each recursive call to createLevelLinkedList receives a reference to the same instance of the ArrayList.
Therefore, once the TreeNode 2 is added to the ArrayList (or, to be exact, to one of the LinkedLists contained within the ArrayList), it stays there throughout the execution of the recursive method. It doesn't disappear when the invocation of createLevelLinkedList that added it to the list returns.
Related
My method should add the associated key/value pair to the trie and if the key is already in the trie, the value should be updated. However I am not quite sure what Im doing wrong, its my first time using tries.
So I am currently working on my put method and I have the following:
public void put(TrieMapNode current, String curKey, String value){
if(current.getChildren().containsKey(curKey))
value = current.get(key);
curKey =value;
put(current.getChildren().get(curKey), curKey, value);
}
Any help would be greatly appreciated thanks!
In your current implementation, you will not benefit from the advantages of a trie. That is because at the root node, you have one child for each string you encounter.
That is not the way a trie is built. Each node of your trie can have at most one child per character (the elements that form strings).
So your method should look more like the following:
public void put(TrieMapNode current, String key, String value, int depth){
if (depth == key.length()){
current.value = value;
} else {
char curChar = key.charAt(depth);
if(!current.getChildren().containsKey(curChar)){
TrieMapNode newNode = new TrieMapNode();
current.getChildren().put(curChar, newNode);
}
put(current.getChildren().get(curChar), curKey, value, depth + 1);
}
The main mistake you did was to consider the key as a whole when inserting/updating in your trie. This would have resulted in a root node having one child node for each key in your map (so a ton of children), but with a very limited depth (the root node, its children and that's it).
In the implementation I proposed you, a node has one child per possible character (a bounded number, 26, 52, anyway a small and bounded number).
And its depth is not limited to one, because as you can see in the else block, we create a node if the one we look for did not exist (when you start you only have a root node, so you need to plan for the case where new node are created), and we also call recursively put on a child of the current node. So the value will be stored at a depth equal toi the length of its key.
I am trying to return a list of Strings of the nodes whose data is "directory" by returning its true name as children.get(0).children.get(0).data
So far, when I go through the tree, it can find the nodes and add the data that Im looking for, but as I add those strings in the List and them System.out.println the list out, the list changes. It can reset, remove Strings, etc.
Right before the return statement, I print off the list. It is not what gets returned.
!!!beforeoutput[Pictures, Pictures2.0, Pictures, Pictures2.0] //print of the list
!!!beforeoutput[Movies and Pictures, Movies, Pictures] //print of the list
getdirectories [Movies and Pictures, Movies, Pictures] //actual output
Someone had told me to define the list in the global scope, and I did, and literally nothing happened.
I guess what I'm asking for is how does one properly query through a tree. I know its recursive, but when adding the values in the list, it messes up the list.
My method's code + the console + an example tree is posted here: http://pastebin.com/9nXvcCNS
I don't understand what you are trying to actually do here, as your code is messy and fussy. You need to understand that when you return a value from a recursive function call, it will return it to a point from where it has previously been called.
If you have a structure like this,
a
| - b
| - c
where each item is represented as
class Node{
String data;
Node nextNode;
}
and would like your list to contain Strings "a", "b", and "c", you wold have to write something like this:
List<String> allDirectories = new ArrayList<String>();
getDirectories(allDirectories);
private void getDirectories(List<String> allDirectories) {
//somehow get next node
Node node = getNextNode();
//if next node is null, or terminating node: return
if (node == null) return;
allDirectories.add(node.getData());
getDirectories(allDirectories);
}
In other words, try passing your list as a parameter to a method, and don't reset it at the beginning of a function call.
I am just starting out with java and recursive methods and i need some help:
I need to determine if two Binary Search Trees has exactly the same set of elements, regardless of the structure of the tree.
I have written a method that checks if the the tree contains an element and its called contains()
this is what i got so far:
public boolean sameContents(Node n2) {
if (contains(n2, n2.key) && n2.left == null && n2.right == null) { return true; }
if (contains(n2, n2.key) && n2.left != null) { sameContents(n2.left); }
if (contains(n2, n2.key) && n2.right != null) { sameContents(n2.right); }
return false;
}
Basicly my idea is that the method is running as long as a node still has a child, and if the trees match.
I call the method with for example testTree1.sameContents(testTree2); but the method always returns false...
Can someone point out how this should be done?
The best way to do this is with an Iterator object - if two binary search trees contain the same elements then their iterators' next methods should return the same values (even if their structures are different).
// returns true if the trees are equivalent, else false
Iterator itr1 = tree1.getIterator();
Iterator itr2 = tree2.getIterator();
while(itr1.hasNext() && itr2.hasNext()) {
if(!itr1.next().equals(itr2.next())) {
return false;
}
}
return !itr1.hasNext() && !itr2.hasNext(); // returns true if trees were the same size, else false
You ought to already have an inorder binary tree traversal method, so you've already got an Iterator - just add an ArrayList/Stack to take the place of the call stack so that you can pause the traversal (whenever you would be making a recursive method call, store the current node to your Stack)
There is another way to do that. You can convert your trees into string representations, using pre-order traversal or in-order traversal. It will take O(n) time. Than you can check whether these strings equal or not. It can be done in O(n) time too. So, the total running time is O(n).
This method looks similar to the solution with iterators but this one is more generic, since can be used for 'is-subtree' task (chechs wether tree t1 is subtree of t2). In this case use can use isSubstring() method instead of equals(). If tree t1 is subtree of t2 than t1's string representaion is substring of t2's. The isSubstring() can be done in O(log n) time.
Can you do a inorder traversal on both trees and check if the result of both the traversals are same. If same, could we assume that both trees have the same set of elements.
I am working on assignment for school. It manly consists of a method that takes as input a binary tree and returns a double threaded tree. Eg(if left child = null then left child will be connected with preceding inorder parent and if right child = null the it will link to its inorder succesor. Now I have an idea for the implementation...
I iterate recursively trough the original BINARY tree and store into an array the inorder traversal. Now, because my teachers implementation requires that threaded trees be a different class from binary. I must traverse again trough the binary tree and convert each node from binaryNode to threadedNode thus having at the end a "duplicate" of the initial BinaryTree but as Threadedtree type. After I do this I traverse again trough this threadedTree and whenever i see a null left or right child I refer to the inorder arraylist and find the threads.
Now as you might have noticed this is extremely inefficient, i am essentially traversing the tree 3 times. My professor has stated that this could be done recursively with only one traversal, essentially converting to threadedNode and finding the threads all at once. I have tried multiple ways but i can not find one that works. Does anyone have any kind of tip or some way i can implement it? Thanks
This is the method as specified by the instructor
public static <T> ThreadedNode<T> thread(BinaryNode<T> root)
{
//threads a binary tree
}
The instructor is correct. One traversal is sufficient.
Traverse the original binary tree, creating new ThreadedNodes as you walk this tree.
public static <T> ThreadedNode<T> thread(BinaryNode<T> root) {
// We'll be keeping track of the "previous" node as we go, so use
// a recursive helper method. At first, there is no previous.
return threadHelper(root, null);
}
private static <T> ThreadedNode<T> threadHelper(BinaryNode<T> n, ThreadedNode<T> previous) {
// Create a new threaded node from the current root. Note that the threaded nodes
// are actually created in "preorder". Assume the ThreadedNode constructor sets
// the left, right, threadLeft, and threadRight fields to null.
ThreadedNode<T> t = new ThreadedNode<T>(n.getData());
// First go down the left side, if necessary.
if (n.getLeft() != null) {
// If there is a left child we have to descend. Note that as we go down the
// left side the previous doesn't change, until we start "backing up".
t.left = threadHelper(n.getLeft(), previous);
previous = t.left;
} else {
// If there is no left child, connect our left thread to the previous.
t.threadLeft = previous;
}
// Now before we go down the right side, see if the previous
// node (it will be in the left subtree) needs to point here.
if (previous != null && previous.right == null) {
previous.threadRight = t;
}
if (n.getRight() != null) {
// If there is a right child we can descend the right. As we go down we
// update previous to the current node. We do this just by passing the current
// node as the second parameter.
t.right = threadHelper(n.getRight(), t);
} else {
// No right child, no worries. We'll hook up our thread-right pointer
// later.
}
return t;
}
Consider the tree (A (B (D) ()) C). The first node you hit in an inorder traversal is D. There is no previous node. So save D as previous. Then the next node you hit is B. The previous node was D, which had no right child, so add a threaded right pointer from D to B. Then set previous to B and continue. Next you hit A. B had no right child, so add a threaded right link from B to A. A has a right child so continue, setting previous to A. The next node is C. C has no left child, so add a threaded left link from C to the current value of previous, which is A.
You could skip the second trip of traversal that you mention in your method. You could convert the nodes from BinaryNode to ThreadedNode on the fly. You'd still need to traverse twice, I think, for the inorder traversal, and for finding the threads and converting it to aThreadedTree.
For conversion on the fly, you could use the method that your instructor has given.
HTH!
My dipslay function of linked list is as follows:-
public void display()
{
cur = first;
if(isEmpty())
{
System.out.println("no elements in the list");
}
else
{
System.out.println("elements in the list are:");
do {
System.out.println(first.data);
first = first.link;
} while(first.link!=null);
first=cur;
}
where curr and first are references of class node
public class node
{
int data;
Node link=null;
}
why is this function only printing the last element?
The function looks more or less correct. However why are you setting cur to first and then using first to do the iteration? Just use cur in the iteration so you don't have to reset first.
Check to make sure you're adding nodes into the list correctly. So if you think there are 3 elements in the list, run this in display():
System.out.println(first.data);
System.out.println(first.link.data);
System.out.println(first.link.link.data);
This is to check if your links are correct.
It is not possible to say for sure, but it is probable that your list actually contains only one element; i.e. that the code that creates the list is broken.
I should also point out that the display method should use a local variable to step through the elements. If you use an instance variable (e.g. first) you are liable to get different methods interfering with each other.
Finally, your test for the end of the list is incorrect. Think carefully about what first and first.link point at when the while test is executed.