After what #hyde told me, this is what I did:
Node<E> current = root;
int count = 0;
public int getNumberOfInteriorNodes() {
if (current == null || (current.left == null && current.right == null)) {
return count;
}
else {
if (current.right != null) {
Node<E> tmp = current;
current = current.right;
count += getNumberOfInteriorNodes();
current = tmp;
}
if (current.left != null) {
Node<E> tmp = current;
current = current.left;
count += getNumberOfInteriorNodes();
current = tmp;
}
return count + 1;
}
}
Below is what my test method looks like:
public static void testGetNumberOfInteriorNodes() {
BinarySearchTree<Integer> t;
t = new BinarySearchTree<Integer>();
Assert.assertEquals(0, t.getNumberOfInteriorNodes());
t.add(2);
Assert.assertEquals(0, t.getNumberOfInteriorNodes());
t.add(1);
Assert.assertEquals(1, t.getNumberOfInteriorNodes());
t.add(5);
Assert.assertEquals(1, t.getNumberOfInteriorNodes());
t.add(4);
Assert.assertEquals(2, t.getNumberOfInteriorNodes());
t.add(3);
Assert.assertEquals(3, t.getNumberOfInteriorNodes());
t.add(6);
Assert.assertEquals(3, t.getNumberOfInteriorNodes());
}
My test fails at the 3rd assertion with the error. Count never goes above zero. Here is the error I get:
Failure: junit.framework.AssertionFailedError: expected:<1> but was:<0>
Any further help would be appreciated.
Your problem is, you have just one shared current variable when you are using recursion. It will get overwritten in recursive calls. Instead, you must pass it as parameter, so your recursive function needs to be:
public int getNumberOfInteriorNodes(Node<E> current)
And on first call (somewhere else in your code) you pass root to it:
... = getNumberOfInteriorNodes(root);
Then you need to pass modified value in recursive call, for right side:
count += getNumberOfInteriorNodes(current.right);
And same for left side, naturally. No return here, otherwise it would return and not calculate the other side! Also no +1, if both right and left side exist then it would be +2. Instead, return count + 1; at the end of the method (yep, you do need it).
Also, in your first if, no point testing if root == null, it does not do anything useful (nothing harmful either in this case, but it's still clutter which makes it harder understand the code, and may become a problem if you change the code).
Then you also seem to have this: int count==0;;
Does that even compile, or is it a copy-paste error? You should use assignment int count = 0;
If you have limitation of not having parameters for the method, you need to restore value of current after the call. Here's code for the right side, do same for the left side:
if (current.right!=null) {
Node<E> tmp = current;
current = current.right;
count += getNumberOfInteriorNodes();
current = tmp;
}
Note that for "real" code, this would be quite a stupid way to do recursion.
If this "no parameters" is just API limitation, then the usual way to solve this is with a private helper method:
public int getNumberOfInteriorNodes() {
return recNumberOfInteriorNodes(root)
}
private int recNumberOfInteriorNodes(Node<E> current) {
...
}
Here's some code that does the trick. Btw: Nodes with no children are leaves.
class Node {
Node left;
Node right;
}
class Main {
void test() {
Node root = new Node();
Node leftleft = new Node();
Node left = new Node();
Node right = new Node();
Node rightright = new Node();
Node rightleft = new Node();
root.left = left;
root.right = right;
left.left = leftleft;
right.left = rightleft;
right.right = rightright;
int c = getLeaves(root);
}
int getLeaves(Node node) {
if (node == null)
return 0;
if (node.left == null && node.right == null)
return 1;
return getLeaves(node.left) + getLeaves(node.right);
}
}
Related
public static SinglyLinkedListNode insertNodeAtPosition(SinglyLinkedListNode llist, int data, int position) {
if(llist == null) {
llist = new SinglyLinkedListNode(data);
return llist;
} else {
for (int i = 0; i < position-1; i++) {
llist = llist.next;
}
SinglyLinkedListNode temp = llist;
llist.next = new SinglyLinkedListNode(data);
llist = llist.next;
llist.next = temp.next;
return llist;
}
}
This is my code to place a custom index node in LinkedList. But hackerrank is not accepting my code. What's wrong with my algorithm?
The problem is that your code always returns the newly created node, but you should always return the first node in the list, which either is what it was when you got it, or is the new node in case the position was zero.
What to look at:
I'll not provide the corrected code, but will give you two hints:
By moving llist ahead in the for loop, you lose the reference to that first node, so use a different variable for walking through the list.
Also, you should deal specifically with the case where position is 0, as this is the only case where the returned value is not the original llist value, but the new node's reference, much like you have in the if block.
Easiest solution No need of explaination :
Solution :
static SinglyLinkedListNode insertNodeAtPosition(SinglyLinkedListNode head, int data, int position) {
if (head == null) return null;
SinglyLinkedListNode temp = new SinglyLinkedListNode(data);
if (position == 0) {
temp.next = head;
return temp;
}
SinglyLinkedListNode p = head;
for (int i = 0; i< position-1; i++) {
p = p.next;
}
SinglyLinkedListNode next = p.next;
p.next = temp;
temp.next = next;
return head;
}
The problem requires you to return a linked list. When we are asked to return a linked list, actually we return the first node of the linked list.
So, your problem is the returned value in your code script is not the first node of the linked list.
The simplest solution is that you keep the first node in another variable, and
return that variable after you have done the insert thing.
for example:
SinglyLinkedListNode dumyNode = llist;
......
return dumyNode;
Suppose given the correct Node class, you can try this approach (without index collision case):
private Node find(int index) {
Node curr = head;
for (int i = 0; i < index; i++)
curr = curr.next;
return curr;
} // end find()
public Object get(int index) throws IndexOutOfBoundsException {
if (index >= 0 && index < size) {
Node curr = find(index);
return curr.data;
} else {
throw new IndexOutOfBoundsException();
} // end if - else
} // end get()
public void add(Object data, int index) throws IndexOutOfBoundsException {
if (index >= 0 && index < size + 1) {
if (index == 0)
head = new Node(data);
else {
Node prev = find(index - 1);
prev.next = new Node(data);
} // end if - else
size++;
} else {
throw new IndexOutOfBoundsException();
} // end if - else
} // end add()
I've written a remove function for a binary search tree that uses a while loop to navigate to the specific node to be removed. However, it's never getting there - it just iterates an unknown number of times and then gives me a NullPointerException.
I was wondering if it was an error in my traversal logic, but it's exactly the same as in my add function, which works perfectly.
void remove(Comparable newObject){
if (!isEmpty()){
Node curr = new Node();
curr = root;
boolean isFound = false;
while (!isFound){
if (curr.data.compareTo(newObject) == 0){
if (curr.hasChildren()){
Node replaceNode = new Node();
if (curr.leftChild == null){
replaceNode = curr.rightChild;
while (replaceNode.leftChild != null){
replaceNode = replaceNode.leftChild;
}
} else {
replaceNode = curr.leftChild;
while (replaceNode.rightChild != null) {
replaceNode = replaceNode.rightChild;
}
}
replaceNode.leftChild = curr.leftChild;
replaceNode.rightChild = curr.rightChild;
replaceNode.parent = curr.parent;
curr = replaceNode;
} else {
curr.data = null;
curr.parent = null;
}
listSize--;
isFound = true;
} else if (curr.data.compareTo(newObject) == 1) {
curr = curr.leftChild;
} else {
curr = curr.rightChild;
}
}
}
}
The data set I'm using yields a root with a left child, and then a right child off of that. The node to be removed is the first (left) child. However, the line that's giving the NullPointerException is
if (curr.data.compareTo(newObject) == 0){
and I'm really not sure at all what's causing this. Any and all help is appreciated greatly.
First of all don't initialize the variable as a new Node(), you're creating new Nodes you're not gonna use. Do it more like this:
void remove(Comparable newObject){
if (!isEmpty()){
Node curr = root;
and then again your replaceNode:
if (curr.hasChildren()){
Node replaceNode;
and I think it's not working, because in the end of the code, you rewrite curr to its children, but what if it doesn't have children? Then you try to compare null object with some object and that's why I think it throws NullPointerException.
I am given two data structures of Nodes, and I am supposed to combine them into one single Node with alternating data structures. The data structures may or may not be of equal lengths.
I have already attempted this problem and I have checked over my code, but it still isn't correct. I have written other methods that I use in this one particular method, so I will post the code for those too. I came up with my method by looking at examples of how the data organization for this particular problem works.
Get the head of the Node list:
public static <E> Node<E> getHead(Node<E> current) {
Node<E> head = null;
while (current != null) {
head = current;
current = current.previous;
}
return head;
}
Get the number of Nodes in the data structure:
public static <E> int countNodes(Node<E> current) {
int count = 0;
while (current != null) {
count++;
current = current.next;
}
return count;
}
Note that I have tested these two methods (getHead and countNodes) and they have proven to be correct. I have posted them to see if they are missing something.
The Node class itself was written by my instructor and has been tested to be correctly written
public static class Node<E> {
public Node<E> next;
public Node<E> previous;
public E data;
public Node(E d) {
data = d;
}
public String toString() {
if (next == null)
return "";
return data + ", " + next.toString();
}
public boolean equals(Object o) {
Node<E> node = (Node<E>) o;
if (node == null)
return false;
Node<E> current = this;
while (current != null && node != null) {
if (!current.data.equals(node.data)) {
return false;
}
current = current.next;
node = node.next;
}
return current == null && node == null;
}
}
Finally, the method that I am having problems with: (Updated with edits)
public static <E> Node<E> combineNodes(Node<E> current, Node<E> current2) {
Node<E> newNode = null;
int currentSize = countNodes(current);
int current2Size = countNodes(current2);
int size = Math.max(currentSize, current2Size);
for (int i = 0; i < size; i++) {
if (i <= currentSize - 1) {
Node<E> node = new Node<E>(current.data);
newNode.next = node;
node.previous = newNode;
newNode = newNode.next;
current = current.next;
}
if (i <= current2Size - 1) {
Node<E> node = new Node<E>(current2.data);
newNode.next = node;
node.previous = newNode;
newNode = newNode.next;
current2 = current2.next;
}
}
return getHead(newNode);
}
Again, I have looked through the code and I feel like it should work. Is there anything that I am missing or doing wrong?
Edit
I should have included the test case that I was given. My instructor is using the JUnit test case library for the assignment. This is the test case that I have to pass:
#Test
public void combineNodesTest1() {
LinkedData.Node<String> node = makeStructure(10); // Makes a data structure of Nodes from "Fred 0" to "Fred 9"
LinkedData.Node<String> node2 = makeStructure(10);
LinkedData.Node<String> ret = new LinkedData.Node<String>("Fred 0");
ret.next = new LinkedData.Node<String>("Fred 0");
LinkedData.Node<String> r = ret.next;
for(int i = 1; i<10;i++) {
r.next = new LinkedData.Node<String>("Fred "+i);
r = r.next;
r.next = new LinkedData.Node<String>("Fred "+i);
r = r.next;
}
LinkedData.Node<String> answer = LinkedData.combineNodes(node, node2); // Method that I wrote
assertEquals(ret, answer);
}
The makeStructure() method is correctly written.
Edit 2
I have updated the code to actually link the nodes together, but it is still wrong. I'd like to know what I'm doing wrong now.
Thanks,
Steward
From my perspective, you don't change any of pointers (next, previous) in your combineNodes method. You only traverse the structure. What is missing in the first if is
newNode = current;
newNode.next = current2;
current = current.next;
and then the following in the second if
newNode = current2;
newNode.next = current;
current2 = current2.next;
So I've been trying to sort a linked list using merge sort, I found this code and tried to work on it, but it doesn't seen to really work?
What could be the problem with it? I'm not quite sure about the getMiddle method although I know it should get the middle value of the list in order to work on 2 lists from the list itself
Here's the code;
public Node mergeSort(Node head) {
if (head == null || head.link == null) {
return head;
}
Node middle = getMiddle(head);
Node sHalf = middle.link;
middle.link = null;
return merge(mergeSort(head), mergeSort(sHalf));
}
public Node merge(Node a, Node b) {
Node dummyHead;
Node current;
dummyHead = new Node();
current = dummyHead;
while (a != null && b != null) {
if ((int) a.getData() <= (int) b.getData()) {
current.link = a;
a.link = a;
}
else {
current.link = b;
b.link = a;
}
current = current.link;
}
current.link = (a == null) ? b : a;
return dummyHead;
}
public Node getMiddle(Node head) {
if (head == null) {
return head;
}
Node slow, fast;
slow = fast = head;
while (fast.link != null && fast.link.link != null) {
slow = slow.link;
fast = fast.link.link;
}
return slow;
}
In the main method:
Object data;
MyLinkedList list = new MyLinkedList(); //empty list.
for (int i = 0; i < 3; i++) { //filling the list
data = console.nextInt();
list.insertAtFront(data);
}
System.out.print("Print(1): ");
list.printList();
list.mergeSort(list.getHead());
System.out.print("List after sorting: ");
list.printList();
One problem is the getMiddle method doesn't correctly return the middle Node.
Consider a linked list with 5 Nodes (a, b, c, d, e)
head, slow, and fast all begin at index 0 (a).
After the first iteration of the while loop, slow is at 1 (b) and fast is at 2 (c); after the second iteration, slow is at 2 (c) and fast at 4 (e). These are both not null, so another iteration happens, putting slow at at 3 (d) and fast at null. Since fast is null, the while loop is exited and slow is returned; however slow has node 3 (d) rather than the middle node, 2 (c).
An alternate way to get the middle node would be to simply use the number of nodes:
public Node getMiddle(Node head) {
Node counter = head;
int numNodes = 0;
while(counter != null) {
counter = counter.link;
numNodes++;
}
if(numNodes == 0)
return null;
Node middle = head;
for(int i=0; i<numNodes/2; i++)
middle = middle.link;
return middle;
}
I your mergeSort method is fine, but technically it only needs to return head if head.link is null, not if head itself is null (since that would never happen anyhow):
public Node mergeSort(Node head) {
if (head.link == null) {
return head;
}
// same
}
Most importantly, your merge method. You can write a public void setData(Object) method in your Node class to make this easier. The following code should work, although I can't claim it's the best/most efficient way to do the job
public Node merge(Node a, Node b) {
Node combined = new Node();
Node current = combined;
while(a != null || b != null) {
if(a == null)
addNode(current, b);
if(b == null)
addNode(current, a);
if((int)a.getData()<(int)b.getData())
addNode(current, a);
else
addNode(current, b);
}
return combined;
}
Uses the following helper method:
public void addNode(Node n1, Node n2) {
n1.setData((int)n2.getData());
n1.link = new Node();
n1 = n1.link;
n2 = n2.link
}
So the app reads from an external file a bunch of strings, each on a separate line.
For example:
and
cake
here
It is not arranged in any particular order. I need to read these letters and put them into linked list and finally sort them.
I need help on doing that:
Here is the current code:
import java.util.*;
import java.io.*;
public class LinkedList
{
static File dataInpt;
static Scanner inFile;
public static void main(String[] args) throws IOException
{
dataInpt=new File("C:\\lldata.txt");
inFile=new Scanner(dataInpt);
Node first = insertInOrder();
printList(first);
}
public static Node getNode(Object element)
{
Node temp=new Node();
temp.value=element;
temp.next=null;
return temp;
}
public static void printList(Node head)
{
Node ptr; //not pointing anywhere
for(ptr=head;ptr!=null;ptr=ptr.next)
System.out.println(ptr.value);
System.out.println();
}
public static Node insertInOrder()
{
Node first=getNode(inFile.next());
Node current=first,previous=null;
Node last=first;
int count=0;
while (inFile.hasNext())
{
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) < 0)
{
current.next=last;
last=current;
}
previous=current;
current=getNode(inFile.next());
}
return last;
}
}
But that gives an infinite loop with "Cat".
Here is the data file:
Lol
Cake
Gel
Hi
Gee
Age
Rage
Tim
Where
And
Kite
Jam
Nickel
Cat
Ran
Jug
Here
Okay, self-study. Split the reading and inserting. Though old and new code both have 14 lines of code,
it makes it more intelligable.
public static Node insertInOrder() {
Node first = null;
while (inFile.hasNext()) {
String value = inFile.next().toString();
first = insert(first, value);
}
return first;
}
/**
* Insert in a sub-list, yielding a changed sub-list.
* #param node the sub-list.
* #param value
* #return the new sub-list (the head node might have been changed).
*/
private static Node insert(Node node, String value) {
if (node == null) { // End of list
return getNode(value);
}
int comparison = node.value.compareTo(value);
if (comparison >= 0) { // Or > 0 for stable sort.
Node newNode = getNode(value); // Insert in front.
newNode.next = node;
return newNode;
}
node.next = insert(node.next, value); // Insert in the rest.
return node;
}
This uses recursion (nested "rerunning"), calling insert inside insert. This works like a loop, or work delegation to a clone, or like a mathematical inductive proof.
Iterative alternative
also simplified a bit.
private static void Node insert(Node list, String value) {
Node node = list;
Node previous = null;
for (;;) {
if (node == null || node.value.compareTo(value) >= 0) {
Node newNode = getNode(value);
newNode.next = node;
if (previous == null)
list = newNode;
else
previous.next = newNode;
break;
}
// Insert in the rest:
previous = node;
node = node.next;
}
return list;
}
public static Node insertInOrder()
{
Node first=getNode(inFile.next());
Node current=first,previous=null;
Node last=first;
int count=0;
while (inFile.hasNext())
{
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) < 0)
{
current.next=last;
last=current;
}
previous=current;
current=getNode(inFile.next());
}
return last;
}
First of all, you never do anything with the last line read from the file, so that's not ever inserted. You have to read the line and create the new Node before relinking next pointers.
Then, if last and previous refer to the same Node and the data of current is larger than that of previous,
if (previous!=null
&& ((String)current.value).compareTo((String)previous.value) > 0)
{
last.next=previous;
previous=last;
}
You set last.next = last, breaking the list. From the code (in particular the absence of a sort(Node) function), it seems as though you want to sort the list as it is created. But you only ever compare each new Node with one other, so that doesn't maintain order.
For each new node, you have to find the node after which it has to be inserted, scanning from the front of the list, and modify current.next and the predecessor's next.
In relatively simple code like that in your question, a good exercise to understanding it is to work through a few interations of your loop, inspecting the values of all your local variable to see the effect of your code. You can even do it by hand if the code is simple. If it is too difficult to do by hand, your code is probably too complicated. If you can't follow it, how can you know if you are doing what you intend. For example, I could be wrong, but this appears the be the state at the top of each iteration of the loop. It starts falling apart on the third time through, and by the fourth you have a severe problem as your list becomes disjointed.
1)last = first = Lol, current = previous = null
Lol->null
2)last = first = previous = Lol, current = Cake
Lol->Lol
3)first = Lol, last = Cake, previous = Cake, current = Gel
Cake->Lol->Lol
4)first = Lol, last = Cake, previous = Cake, current = Hi
Cake->Gel, Lol->Lol
Quite honestly, if I were running the course, I would consider the correct answer to be:
List<String> list = new LinkedList<String>();
// read in lines and: list.add(word);
Collections.sort(list);
Ok, I don't remember exactly school theory about insertion sort, but here is somehow a mix of what I think it is and your code:
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class LinkedList {
public static class Node {
public String value;
public Node next;
}
static File dataInpt;
static Scanner inFile;
public static void main(String[] args) throws IOException {
inFile = new Scanner("Lol\r\n" + "Cake\r\n" + "Gel\r\n" + "Hi\r\n" + "Gee\r\n" + "Age\r\n" + "Rage\r\n" + "Tim\r\n" + "Where\r\n"
+ "And\r\n" + "Kite\r\n" + "Jam\r\n" + "Nickel\r\n" + "Cat\r\n" + "Ran\r\n" + "Jug\r\n" + "Here");
Node first = insertInOrder();
printList(first);
}
public static Node getNode(String element) {
Node temp = new Node();
temp.value = element;
temp.next = null;
return temp;
}
public static void printList(Node head) {
Node ptr; // not pointing anywhere
for (ptr = head; ptr != null; ptr = ptr.next) {
System.out.println(ptr.value);
}
System.out.println();
}
public static Node insertInOrder() {
Node current = getNode(inFile.next());
Node first = current, last = current;
while (inFile.hasNext()) {
if (first != null && current.value.compareTo(first.value) < 0) {
current.next = first;
first = current;
} else if (last != null && current.value.compareTo(last.value) > 0) {
last.next = current;
last = current;
} else {
Node temp = first;
while (current.value.compareTo(temp.value) < 0) {
temp = temp.next;
}
current.next = temp.next;
temp.next = current;
}
current = getNode(inFile.next());
}
return first;
}
}
And it works like a charm. Of course this far from optimal, both in terms of performance and code reuse.