I'm getting a pointer exception error, it's saying my root is null. But I know it's null! I thought the way I had programmed it is so that if the root is null, it adds a node in that space.
Printing out the list...
73,M&M's Fun size
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Node.add(Node, Entry)" because "this.root" is null
at BinarySearchTree.add(BinarySearchTree.java:71)
at BinarySearchTree.main(BinarySearchTree.java:26)
Here is my main snippet -
File myObj = new File("halloween calories.txt");
Scanner myReader = new Scanner(myObj);
Integer.parseInt(myReader.nextLine());
BinarySearchTree bst = new BinarySearchTree();
System.out.println("Printing out the list...");
while (myReader.hasNextLine()) {
String string = myReader.nextLine();
if (string.equals("END")) break;
String[] parts = string.split(",");
int part1 = Integer.parseInt(parts[0]);
String part2 = parts[1];
Entry a = new Entry(part1, part2);
System.out.println(a.key + "," + a.value);
bst.add(a);
}
Where I read in a file, split it, and add the two halves as an entry with an int key and String value.
I need to call a method from my Node from my BinarySearchTree class
This is the BinarySearchTree class method
public void add(Entry entry) {
/*Adds the key to the correct position in the BST. If the key already
exists, do nothing. So, basically, you are creating a proper-set of
numbers.*/
root.add(root, entry);
}
Thhis is from my Node class.
public Node add(Node current, Entry entry) {
/*Adds the key to the correct position in the BST. If the key already
exists, do nothing.*/
if (current == null) {
current = new Node(entry);
} else if (current.entry.key < entry.key) {
// if current root data is greater than the new data then now process the left sub-tree
add(current.left, entry);
} else {
// if current root data is less than the new data then now process the right sub-tree
add(current.right, entry);
} return current;
}
I've been beating my head against the wall trying to figure this out, all the code I've googled looks identical to my own.
Having the same problem I think with the print function! I think I keep declaring the root as null but I have very specific parameters for this assignment which is part of the reason it's been so difficult for me. I actually managed to get it working perfectly by making the functions static, but my professor said I need to be calling on the object itself.
You are not setting the corresponding fields of the current node after each recursive calls in the if statement.
public Node add(Node current, int entry) {
/*Adds the key to the correct position in the BST. If the key already
exists, do nothing.*/
if (current == null) {
current = new Node(entry);
} else if (current.entry.key < entry) {
// if current root data is greater than the new data then now process the left sub-tree
current.left = add(current.left, entry);
} else {
// if current root data is less than the new data then now process the right sub-tree
current.right = add(current.right, entry);
} return current;
}
Related
I am trying to solve LeetCode question 2096. Step-By-Step Directions From a Binary Tree Node to Another:
You are given the root of a binary tree with n nodes. Each node is uniquely assigned a value from 1 to n. You are also given an integer startValue representing the value of the start node s, and a different integer destValue representing the value of the destination node t.
Find the shortest path starting from node s and ending at node t. Generate step-by-step directions of such path as a string consisting of only the uppercase letters 'L', 'R', and 'U'. Each letter indicates a specific direction:
'L' means to go from a node to its left child node.
'R' means to go from a node to its right child node.
'U' means to go from a node to its parent node.
Return the step-by-step directions of the shortest path from node s to node t.
I have converted the tree to a graph using an adjacency list. For each node, I store the adjacent nodes as well as the direction. For example, suppose we have a tree [1,2,3], then at the end of traversal, we obtain a HashMap that looks like {1:[(2,'L'), (3,'R')], 2:[(1,'U')], 3:[(1,'U')].
I assumed that performing a BFS from startNode to endNode would help me trace the path. But I end up getting an incorrect answer or an extra step if the endNode was in the left but I tried the right node first or if I tried the right node first and the endNode was left.
I found on Stack Overflow How to trace the path in a Breadth-First Search? and it seems that my approach appears to be correct (I don't know what I am missing). I don't understand the purpose or the need to backtrace either.
My code is below:
public class StepByStep {
HashMap<TreeNode, HashMap<TreeNode, String>> graph = new HashMap<TreeNode, HashMap<TreeNode, String>>();
public static void main(String argv[]) {
TreeNode root = new TreeNode (5);
root.left = new TreeNode(1);
root.right = new TreeNode(2);
root.left.left = new TreeNode(3);
root.right.left = new TreeNode(6);
root.right.right = new TreeNode(4);
StepByStep sbs = new StepByStep();
System.out.println(sbs.getDirections(root, 3, 6));
Set<TreeNode> keys = sbs.graph.keySet();
for(TreeNode key : keys) {
System.out.print(key.val + " ");
HashMap<TreeNode, String> map = sbs.graph.get(key);
Set<TreeNode> nodes = map.keySet();
for(TreeNode node : nodes) {
System.out.print(node.val + map.get(node) + " ");
}
System.out.println();
}
}
public String getDirections(TreeNode root, int startValue, int destValue) {
// we do a inorder traversal
inorder(root, null);
//now we perform a breadth first search using the graph
Set<TreeNode> keys = graph.keySet();
TreeNode start = null;
for(TreeNode key : keys) {
if(key.val == startValue) {
start = key;
break;
}
}
return bfs(start, destValue);
}
public String bfs(TreeNode root, int destValue) {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
HashSet<TreeNode> visited = new HashSet<TreeNode>();
queue.add(root);
StringBuilder sb = new StringBuilder("");
while(!queue.isEmpty()) {
int size = queue.size();
while(size > 0) {
TreeNode current = queue.poll();
if(current.val == destValue) {
return sb.toString();
}
visited.add(current);
HashMap<TreeNode, String> map = graph.get(current);
Set<TreeNode> keys = map.keySet();
for(TreeNode key : keys) {
if(!visited.contains(key)) {
sb.append(map.get(key));
queue.add(key);
}
}
--size;
}
}
return "";
}
public void inorder(TreeNode root, TreeNode parent) {
if (root == null)
return;
inorder(root.left, root);
inorder(root.right, root);
if (root.left != null) {
if (!graph.containsKey(root)) {
graph.put(root, new HashMap<TreeNode, String>());
}
HashMap<TreeNode, String> map = graph.get(root);
map.put(root.left, "L");
graph.put(root, map);
}
if (root.right != null) {
if (!graph.containsKey(root)) {
graph.put(root, new HashMap<TreeNode, String>());
}
HashMap<TreeNode, String> map = graph.get(root);
map.put(root.right, "R");
graph.put(root, map);
}
if (parent != null) {
if (!graph.containsKey(root)) {
graph.put(root, new HashMap<TreeNode, String>());
}
HashMap<TreeNode, String> map = graph.get(root);
map.put(parent, "U");
graph.put(root, map);
}
}
}
What am I missing?
The problem is in bfs: there you add every visited node to sb, but that is wrong, since these nodes are not all on the path from the root to that particular node. Instead, you should consider that every visited node represents its own unique path from the root, which does not include all the nodes that were already visited, just a few of those.
One solution is that you store in the queue not only the node, but also its own move-string (like its private sb), so that you actually store a Pair in the queue: a node and a string buffer.
Once you find the destination, you can then return that particular string.
Alternatively, you'd make life easier if you would perform a depth-first search (with recursion), building the string while backtracking. This will cost less memory. Breadth first is interesting when you need to find a shortest path, but in a tree there is only one path between two nodes, so finding any path is good enough, and that is what a depth-first search will give you.
Finally, I would solve this problem as follows:
Perform a depth first traversal, and collect the steps ("L" or "R") from the root to the start node and the steps from the root to the destination node. These paths only have the letters "L" and "R" as there is no upwards movement.
Remove the common prefix from these paths, so that both paths now start from their lowest common ancestor node.
Replace all letters of the first path (if any) with "U".
Done.
I need implement method who searching next node after any arbitrary key. For example BST has keys {0, 2, 4, 6, 8}. For key 1 result must be 2 and for key 4 result must be 6.
After some research by google and SO, I implement it this way(C#-like pseudocode):
class TreeNode
{
int Key;
TreeNode Left;
TreeNode Right;
}
class Tree
{
TreeNode Root;
TreeNode FindNextNode(int key)
{
TreeNode node = Root;
TreeNode succ = null;
while (node != null) {
if (key >= node.Key) {
node = node.Right;
continue;
}
succ = node;
node = node.Left;
}
return succ;
}
}
Everything seems to be good and even works, but such a simple implementation makes me think that I have missed whatsoever.
Is my implementation correct?
Upd: Picture for discussion
After looking at it for a while, the implementation looks correct in the latest version. There was this error mentioned in the comments:
`if (key >= null) {`
Also the left and right borders seem to be handled correctly. If the search key is beyond the maximum, null is returned. A search below the minimum should also return the first element in the list.
My only concern is that there is no null check for the input parameter. Perhaps some input parameter checking would make this implementation more robust.
I would also prefer not to use continue and use else instead.
Here is a version of this method in Kotlin enforcing non null search parameters and using else instead of continue:
fun next(key: Key): Key? {
var node = root
var succ: Node<Key, Value>? = null
while (node != null) {
if (key >= node.key) {
node = node.right
}
else {
succ = node
node = node.left
}
}
return succ?.key
}
Question: Build a queue class with the enqueue and dequeue methods. However, the language you are using has a bug which does not allow arrays to store more than 5 elements, how would you build that?
I wrote the below code and I was rejected, curious to understand what is the issue and why I was rejected, fyi - this is in technical phone screen.
static LinkedList<Queue<Integer>> list = new LinkedList<Queue<Integer>>();
public static void enQueue(Integer element){
//iterating the linkedlist....
while(true){ //todo
Queue<Integer> curr;
if(list.size() > 0)
curr = list.getLast();
else{
curr = new LinkedList<Integer>();
list.add(curr);
}
if(curr.size() < 5){
curr.add(element);
System.out.println("enqueued:" + element);
break;
} else{
Queue<Integer> newQueue = new LinkedList<Integer>();
newQueue.add(element);
list.add(newQueue); //adding the new Queue of size(5) to the list
break;
}
}
}
public static Integer deQueue(){
LinkedList<Queue<Integer>> node = list;
if(!isEmpty()){
Integer retValue = 0;
while(list.size() > 0){
Queue<Integer> q = node.getFirst();
if(!q.isEmpty()){
retValue = q.poll();
break;
}else{
node.removeFirst();
}
}
return retValue;
}else{
System.out.println("No such element found");
return -1; //throw new NoSuchElementException("no element found");
}
}
public static boolean isEmpty(){
return list.size() == 0;
}
You were rejected, because:
you assumed a pre-existing Queue class, which is what you were supposed to implement.
you used a LinkedList, which already implements a queue-like interface, instead of actually implementing a queue.
You used the LinkedList badly -- there is no reason for any kind of loop at all. You could have just had your enQueue and deQueue call LinkedList.add() LinkedList.pollFirst()
The interviewer really wanted you to actually implement a queue. The array limitation is to force you to use a linked implementation, and the interviewer wanted to see you maintain the links properly.
I guess the question is to check on your implementation of queue data structure with arrays, which cannot be more than size of 5.
I would have something like
Class Queue {
int[][] data;
int maxSize = 25; //5 * 5
int[] front;
int[] rear;
Enqeue(int element) {
//Check for queue full
//Increment front last index, if it crosses 5. Increment previous index
//Use the front index identify data element
//Put the data
}
Dequeue() {
//Check for queue empty
//Use the rear index identify data element
//get the data
//Increment rear last index, if it crosses 5. Increment previous index
//Return the data
}
}
The queue size can be easily scaled to big numbers.
Hope it helps!
Simply put I want to check if a specified word exists or not.
The lookup needs to be very fast which is why I decided to store the dictionary in a trie. So far so good! My trie works without issues. The problem is filling the trie with a dictionary. What I'm currently doing is looping through every line of a plain text file that is the dictionary and adding each word to my trie.
This is understandably so an extremely slow process. The file contains just about 120 000 lines. If anyone could point me in the right direction for what I could do it would be much appreciated!
This is how I add words to the trie (in Boo):
trie = Trie()
saol = Resources.Load("saol") as TextAsset
text = saol.text.Split(char('\n'))
for new_word in text:
trie.Add(new_word)
And this is my trie (in C#):
using System.Collections.Generic;
public class TrieNode {
public char letter;
public bool word;
public Dictionary<char, TrieNode> child;
public TrieNode(char letter) {
this.letter = letter;
this.word = false;
this.child = new Dictionary<char, TrieNode>();
}
}
public class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode(' ');
}
public void Add(string word) {
TrieNode node = root;
bool found_letter;
int c = 1;
foreach (char letter in word) {
found_letter = false;
// if current letter is in child list, set current node and break loop
foreach (var child in node.child) {
if (letter == child.Key) {
node = child.Value;
found_letter = true;
break;
}
}
// if current letter is not in child list, add child node and set it as current node
if (!found_letter) {
TrieNode new_node = new TrieNode(letter);
if (c == word.Length) new_node.word = true;
node.child.Add(letter, new_node);
node = node.child[letter];
}
c ++;
}
}
public bool Find(string word) {
TrieNode node = root;
bool found_letter;
int c = 1;
foreach (char letter in word) {
found_letter = false;
// check if current letter is in child list
foreach (var child in node.child) {
if (letter == child.Key) {
node = child.Value;
found_letter = true;
break;
}
}
if (found_letter && node.word && c == word.Length) return true;
else if (!found_letter) return false;
c ++;
}
return false;
}
}
Assuming that you don't have any serious implementation problems, pay the price for populating the trie. After you've populated the trie serialize it to a file. For future needs, just load the serialized version. That should be faster that reconstructing the trie.
-- ADDED --
Looking closely at your TrieNode class, you may want to replacing the Dictionary you used for child with an array. You may consume more space, but have a faster lookup time.
Anything you do with CLI yourself will be slower then using the built-in functions.
120k is not that much for a dictionary.
First thing I would do is fire up the code performance tool.
But just some wild guesses: You have a lot of function calls. Just starting with the Boo C# binding in a for loop. Try to pass the whole text block and tare it apart with C#.
Second, do not use a Dictionary. You waste just about as much resources with your code now as you would just using a Dictionary.
Third, sort the text before you go inserting - you can probably make some optimizations that way. Maybe just construct a suffix table.
Any XPath like /NodeName/position() would give you the position of the Node w.r.t it's parent node.
There is no method on the XElement (Linq to XML) object that can get the position of the Element. Is there?
Actually NodesBeforeSelf().Count doesn't work because it gets everything even of type XText
Question was about XElement object.
So I figured it's
int position = obj.ElementsBeforeSelf().Count();
that should be used,
Thanks to Bryant for the direction.
You could use the NodesBeforeSelf method to do this:
XElement root = new XElement("root",
new XElement("one",
new XElement("oneA"),
new XElement("oneB")
),
new XElement("two"),
new XElement("three")
);
foreach (XElement x in root.Elements())
{
Console.WriteLine(x.Name);
Console.WriteLine(x.NodesBeforeSelf().Count());
}
Update: If you really just want a Position method, just add an extension method.
public static class ExMethods
{
public static int Position(this XNode node)
{
return node.NodesBeforeSelf().Count();
}
}
Now you can just call x.Position(). :)
Actually in the Load method of XDocument you can set a load option of SetLineInfo, you can then typecast XElements to IXMLLineInfo to get the line number.
you could do something like
var list = from xe in xmldoc.Descendants("SomeElem")
let info = (IXmlLineInfo)xe
select new
{
LineNum = info.LineNumber,
Element = xe
}
static int Position(this XNode node) {
var position = 0;
foreach(var n in node.Parent.Nodes()) {
if(n == node) {
return position;
}
position++;
}
return -1;
}