I'm working on a hackerrank problem and it seems like no matter the variation of the solution I try, I can't get the cycle detection to work.
Here's the code I'm using
static boolean hasCycle(SinglyLinkedListNode head) {
if (head == null) return false;
SinglyLinkedListNode slow, fast;
slow = head;
fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) return true;
}
return false;
}
I can tweak the solution to get the other test to pass, but not both. In this case true is never returned, even when it should be. How can I fix this, what am I doing wrong?
It has to do with Hackerrank itself. I tried my own solution that passed all the tests some time ago but it also failed for cases where there were cycles. So, I took a look at Hackerrank's insertNode method used for creating lists in test cases:
public void insertNode(int nodeData) {
// here a new node object is created each time a method is called
SinglyLinkedListNode node = new SinglyLinkedListNode(nodeData);
if (this.head == null) {
this.head = node;
} else {
this.tail.next = node;
}
this.tail = node;
}
And then how it's used in their main:
public static void main(String[] args) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
int tests = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
for (int testsItr = 0; testsItr < tests; testsItr++) {
int index = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
SinglyLinkedList llist = new SinglyLinkedList();
int llistCount = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
for (int i = 0; i < llistCount; i++) {
int llistItem = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
// a new node is inserted each time so no cycle can be created whatsoever.
llist.insertNode(llistItem);
}
boolean result = hasCycle(llist.head);
bufferedWriter.write(String.valueOf(result ? 1 : 0));
bufferedWriter.newLine();
}
bufferedWriter.close();
scanner.close();
}
As you can see for each llistItem value llist.insertNode(llistItem) is invoked to add an item to the list. This method, however, can't create cycles as it creates a new SinglyLinkedListNode each time. So, even though some llistItem values are the same the nodes containing them are always different.
UPDATE
As of January 5, 2020, Hackerrank tests are fixed and the solution provided by the OP passes all of them.
Tests of this challenge are incorrect, and there are no loops. Check it by printing out head.next....next. You can get NPE where tests waiting for return TRUE. See linked lists generations in other languages.
I was given the following code that is supposed to determine the number of nodes in a tree that have two children...
public int twoChildren(TreeNode<Integer> root){
int counter= 0;
if (root == null)
return 0;
else if (root.right != null && root.left != null)
counter++;
int leftTwoChildren = twoChildren(root.left);
int rightTwoChildren = twoChildren(root.right);
return counter + leftTwoChildren + rightTwoChildren;
}
My job is to identify if this code is doing that, and if it isn't then figure out what the issue is. It all seems to check out with me, but I just wanted to double check that the counter works on this example. Would I even need the two integers for the left and right? I'm not sure. If someone could confirm this checks out or let me know there's an issue I would greatly appreciate it.
Your code will work fine if you return 0 instead of null
if(root==null)
return 0;
You don't need the two integers for left and right, you can return the recursive calls explicitly, and also get rid of counter integer.
public int twoChildren(TreeNode<Integer> root){
if (root == null)
return 0;
if (root.right != null && root.left != null)
return 1 + twoChildren(root.left) + twoChildren(root.right);
return twoChildren(root.left) + twoChildren(root.right);
}
I’ve been doing this problem:
I created one file which takes random numbers and I stored those numbers in a SinglyLinkedList data structure and I'd like to perform a mergeSort to sort these random numbers.
Everything works fine for smaller no of input.
But when I insert 10000 numbers, it starts giving ‘stack_overflow’ error at around 9800 no(at displaying numbers only) and when I insert 0.1 million numbers- it works well till 99700 numbers but then it starts showing errors for the rest of the numbers.
So what exactly the reason would be behind this error (I know it’s because it gets lost in recursive function)
Please help me out here, I'm not able to track the problem which causes this error.
Here's my main method code:
FileReader fr = new FileReader("C://my_folder//file_List.txt");
BufferedReader br = new BufferedReader(fr);
LinkedListNode lln = new LinkedListNode();
String str;
while((str=br.readLine())!=null){
/* This insertAtEnd appends the number to the SinglyLinkedList*/
lln.insertAtEnd(Integer.parseInt(str));
System.out.println(" "+str);
}
/*This method displays the elements of a LinkedList*/
Node res = lln.traverse();
System.out.println("\n");
mergeSortLinkedList ms = new mergeSortLinkedList();
ms.sort(res);
here's my sort method code:
public void sort(Node n){
Node tmp = n;
MergeSort(tmp);
}
Node a;
Node b;
public void MergeSort(Node headRef){
Node head1 = headRef;
if(head1 == null || head1.next == null){
return;
}
System.out.print("hi..");
Node Euler = splitList(head1);
printList(Euler);
}
/* perform merge sort on the linked list */
public Node splitList(Node head1){
Node slow;
Node fast;
Node left, right;
if(head1 == null || head1.next == null){
left = head1;
right = null;
return head1;
}
else{
slow = head1;
fast = head1.next;
while(fast!=null){
fast = fast.next;
if(fast!=null){
slow = slow.next;
fast = fast.next;
}
}
left = head1;
right = slow.next;
slow.next = null;
}
return SortedMerge(splitList(left),splitList(right));
}
/* merge the lists.. */
public Node SortedMerge(Node a, Node b){
Node result = null;
if(a == null){
return b;
}
else if( b == null){
return a;
}
if(a.data < b.data){
result = a;
result.next = SortedMerge(a.next, b);//getting error at this line
}
else{
result = b;
result.next = SortedMerge(a,b.next);//getting error at this line
}
return result;
}
public void printList(Node Euler){
System.out.println("\nPrinting sorted elements");
Node Ref = Euler;
int count = 0;
while(Ref!=null){
count++;
System.out.println(count+"-"+Ref.data);
Ref = Ref.next;
}
}
have you considered using Collections.sort() from the JDK, which will do a merge-sort? Java 8 has also a parallelSort which does a parallel merge-sort.
I’d like to give you a update.
By changing the stack size, I did able to run my program properly.
The reason it was causing
Exception in thread "main" java.lang.StackOverflowError is because it was getting out of stack size.
So I searched around and got this solution.
Go to the project properties- Inside run, go to the VM option and put this in argument -Xss100m to make it run!
Now it is able to sort more than 1 million numbers :D
Other suggestions / solutions are welcome.
Trying to figure out how to sort my doubly linked list.
I get a null pointer exception here:
while (temp.getNext()!=null){
Is there a better approach or any advice to get this going the right way?
public void sort() {
//bubble sort!
boolean swapped = (head != null);
while (swapped) {
swapped = false;
EntryNode temp = head;
//can't swap something with nothing
while (temp.getNext()!=null){
if (temp.getLastName().compareTo(temp.getNext().getLastName()) > 0) {
swapped = true;
//special case for two nodes
if (size == 2) {
//reassign head and tail
tail = temp;
head = temp.getNext();
tail.setPrev(head);
head.setNext(tail);
tail.setNext(null);
head.setNext(null);
}
//if swapping is at head
else {
if (temp == head) {
head = temp.getNext();
temp.setNext(head.getNext());
head.getNext().setPrev(temp);
head.setPrev(null);
head.setNext(temp);
temp.setPrev(head);
}
else {
temp.setNext(temp.getNext().getNext());
temp.setPrev(temp.getNext());
temp.getNext().setNext(temp);
temp.getNext().setPrev(temp.getPrev());
}
}
}
//loop through list
temp = temp.getNext();
}
}
}
Use the merge sort algorithm, is often the best choice for sorting a (single or doubly) linked list. There's already a post discussing the relevant implementation issues.
I think you should check for:
while(temp != null)
because you are already assigning
temp = temp.getNext()
at the end of the while loop.
The simple approach is to put the list contents into an array, use Arrays.sort to sort the array, and finally rebuild the list from the sorted array.
First of all, I swear this is not homework, it's a question I was asked in an interview. I think I made a mess of it (though I did realise the solution requires recursion). Here is the question:
Implement the count() method which returns the number of nodes in a tree. If a node doesn't have either a left or right child, the relevant getXXChild() method will return null
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
// Implement me
}
}
My reason for asking the question is simply curious to see the correct solution, and thereby measure how bad mine was.
Cheers,
Tony
int count() {
Tree right = getRightChild();
Tree left = getLeftChild();
int c = 1; // count yourself!
if ( right != null ) c += right.count(); // count sub trees
if ( left != null ) c += left.count(); // ..
return c;
}
A trivial recursive solution:
int count() {
Tree l = getLeftTree();
Tree r = getRightTree();
return 1 + (l != null ? l.count() : 0) + (r != null ? r.count() : 0);
}
A less trivial non-recursive one:
int count() {
Stack<Tree> s = new Stack<Tree>();
s.push(this);
int cnt = 0;
while (!s.empty()) {
Tree t = s.pop();
cnt++;
Tree ch = getLeftTree();
if (ch != null) s.push(ch);
ch = getRightTree();
if (ch != null) s.push(ch);
}
return cnt;
}
The latter is probably slightly more memory-efficient, because it replaces recursion with a stack and an iteration. It's also probably faster, but its hard to tell without measurements. A key difference is that the recursive solution uses the stack, while the non-recursive solution uses the heap to store the nodes.
Edit: Here's a variant of the iterative solution, which uses the stack less heavily:
int count() {
Tree t = this;
Stack<Tree> s = new Stack<Tree>();
int cnt = 0;
do {
cnt++;
Tree l = t.getLeftTree();
Tree r = t.getRightTree();
if (l != null) {
t = l;
if (r != null) s.push(r);
} else if (r != null) {
t = r;
} else {
t = s.empty() ? null : s.pop();
}
} while (t != null);
return cnt;
}
Whether you need a more efficient or a more elegant solution naturally depends on the size of your trees and on how often you intend to use this routine. Rembemer what Hoare said: "premature optimization is the root of all evil."
I like this better because it reads:
return count for left + count for rigth + 1
int count() {
return countFor( getLeftChild() ) + countFor( getRightChild() ) + 1;
}
private int countFor( Tree tree ) {
return tree == null ? 0 : tree.count();
}
A little more towards literate programming.
BTW, I don't like the getter/setter convention that is so commonly used on Java, I think a using leftChild() instead would be better:
return countFor( leftChild() ) + countFor( rightChild() ) + 1;
Just like Hoshua Bloch explains here http://www.youtube.com/watch?v=aAb7hSCtvGw at min. 32:03
If you get it rigth your code reads...
BUT, I have to admit the get/set convention is now almost part of the language. :)
For many other parts, following this strategy creates self documenting code, which is something good.
Tony: I wonder, what was your answer in the interview.
return (getRightChild() == null ? 0 : getRightChild.count()) + (getLeftChild() == null ? 0 : getLeftChild.count()) + 1;
Or something like that.
Something like this should work:
int count()
{
int left = getLeftChild() == null ? 0 : getLeftChild().count();
int right = getRightChild() == null ? 0 : getRightCHild().count();
return left + right + 1;
}
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
return 1
+ getRightChild() == null? 0 : getRightChild().count()
+ getLeftChild() == null? 0 : getLeftChild().count();
}
}
You can count the tree by traversing it many ways. Simply preorder traversal, the code would be (based on the functions you defined):
int count() {
count = 1;
if (this.getLeftChild() != null)
count += this.getLeftChild().count();
if (this.getRightChild() != null)
count += this.getRightChild().count();
return count;
}
Implement the method:
public static int countOneChild(Node root)
{
...
}
that counts the number of internal nodes in a binary tree having one child. Add the function to tree.java program.
I did it by preorder recurssion. Altough it doesn't exactly follow the interview format by using localRoot, but I think you get the idea.
private int countNodes(Node<E> localRoot, int count) {
if (localRoot == null)
return count;
count++; // Visit root
count = countNodes(localRoot.left, count); // Preorder-traverse (left)
count = countNodes(localRoot.right, count); // Preorder-traverse (right)
return count;
}
public int countNodes() {
return countNodes(root, 0);
}
This is a standard recursion problem:
count():
cnt = 1 // this node
if (haveRight) cnt += right.count
if (haveLeft) cnt += left.count
return cnt;
Very inefficient, and a killer if the tree is very deep, but that's recursion for ya...
int count()
{
int retval = 1;
if(null != getRightChild()) retval+=getRightChild().count();
if(null != getLeftChild()) retval+=getLeftChild().count();
return retval;
}
God I hope I didn't make a mistake.
EDIT: I did actually.
Of course, if you want to avoid visiting every node in your tree when you count, and processing time is worth more to you than memory, you can cheat by creating your counts as you build your tree.
Have an int count in each node,
initialized to one, which
respresents the number of nodes in
the subtree rooted in that node.
When you insert a node, before
returning from your recursive insert
routine, increment the count at the
current node.
i.e.
public void insert(Node root, Node newNode) {
if (newNode.compareTo(root) > 1) {
if (root.right != null)
insert(root.right, newNode);
else
root.right = newNode;
} else {
if (root.left != null)
insert(root.left, newNode);
else
root.left = newNode;
}
root.count++;
}
Then getting the count from any point just involves a lookup of node.count
My first attempt didn't have anything new to add, but then I started to wonder about recursion depth and whether it would be possible to rearrange the code to take advantage of the tail call optimization feature of the latest Java compiler. The main problem was the null test - which can be solved using a NullObject. I'm not sure if TCO can deal with both recursive calls, but it should at least optimize the last one.
static class NullNode extends Tree {
private static final Tree s_instance = new NullNode();
static Tree instance() {
return s_instance;
}
#Override
Tree getRightChild() {
return null;
}
#Override
Tree getLeftChild() {
return null;
}
int count() {
return 0;
}
}
int count() {
Tree right = getRightChild();
Tree left = getLeftChild();
if ( right == null ) { right = NullNode.instance(); }
if ( left == null ) { left = NullNode.instance(); }
return 1 + right.count() + left.count();
}
The precise implementation of NullNode depends on the implementations used in Tree - if Tree uses NullNode instead of null, then perhaps the child access methods should throw NullPointerException instead of returning null. Anyway, the main idea is to use a NullObject in order to try to benifit from TCO.
Questions related to binary tree should be expected in an interview. I would say to take time before any next interview and go through this link. There are about 14 problems solved .You can have a look and how the solution is done. This would give you an idea of how to tackle a problem with binary tree in future.
I know your question is specific to the count method .That is also implemented in the link that i provided
class Tree {
Tree getRightChild() {
// Assume this is already implemented
}
Tree getLeftChild() {
// Assume this is already implemented
}
int count() {
if(this.getLeftChild() !=null && this.getRightChild()!=null)
return 1 + this.getLeftChild().count() + this.getRightChild().count();
elseif(this.getLeftChild() !=null && this.getRightChild()==null)
return 1 + this.getLeftChild().count();
elseif(this.getLeftChild() ==null && this.getRightChild()!=null)
return 1 + this.getRightChild().count();
else return 1;//left & right sub trees are null ==> count the root node
}
}