This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I am working on a basic Hackerrank problem where we append an element to the end of the linked list.
/*
Insert Node at the end of a linked list
head pointer input could be NULL as well for empty list
Node is defined as
class Node {
int data;
Node next;
}
*/
Node Insert(Node head,int data) {
if(head == null) {
Node node = new Node();
head = node;
head.data = data;
head.next = null;
return head;
}
while(head != null) {
head = head.next;
}
head.data = data;
head.next = null;
return head;
}
For some reason, this solution does not compile. I was looking problems other people solved, and they used a temporary node in the non-empty linked list solutions.
You need to create a new node at the end as well.
Also, don't wait until "head==null" or you'll reach the end of the list and you won't know where to insert the node.
You need to go until "head.next==null" so that you end up at the current last node.
Also, if you must always return the Head of the list, you should copy the reference before starting the iteration, as noted in the comments.
Node Insert(Node head,int data) {
if(head == null) {
Node node = new Node();
head = node;
head.data = data;
head.next = null;
return head;
}
Node current = head;
while(current.next != null) {
current = current.next;
}
Node node = new Node();
node.data = data;
node.next = null;
current.next = node;
return head;
}
Related
This is a code that adds a node at the front of the doubly linked list. What I don't understand here is step 4. Right here, it appears to me that it's storing the address of the new_Node into the variable head.prev. The variable head.prev will now hold new-node. This doesn't even make sense because the variable 'head' will also hold new_node. So now we have two variables pointing to the same address.
Even if, in any case, this code was meant to say, new_node = head.prev, that also does not make sense, because the head.prev will be null at this point, and new_node will then point to a null.
// Class for Doubly Linked List
public class DLL {
Node head; // head of list
/* Doubly Linked list Node*/
class Node {
int data;
Node prev;
Node next;
// Constructor to create a new node
// next and prev is by default initialized as null
Node(int d) { data = d; }
}
// Adding a node at the front of the list
public void push(int new_data)
{
/* 1. allocate node
* 2. put in the data */
Node new_Node = new Node(new_data);
/* 3. Make next of new node as head and previous as NULL */
new_Node.next = head;
new_Node.prev = null;
/* 4. change prev of head node to new node */
if (head != null)
head.prev = new_Node;
/* 5. move the head to point to the new node */
head = new_Node;
}
}
The step 4 is needed to connect the prev of the old head to the new head.
This is the situation after step 3:
Then after step 4 the prev of the old head (which was null) is set to point to the new head:
And then step 5 makes head point to the new node (the new head):
If head.prev != null then head is not the first element of the list. This should be checked as a pre-condition, and an IllegalStateException should be thrown. Further processing of the insertion is senseless as the pointer to the first position must be restored.
After step 3, the new_node setup is complete, and the new_node is linked unidirectional by new_node.next to the former first, now second element head. To make the double-link complete, head.prev must be set to the new predecessor head. That is what step 4 does if you omit the if.
public class DLL {
private Node head;
private Node tail;
public void addFirst(int val) {
Node node = new Node(val);
if (head == null)
tail = node;
else {
node.next = head;
head.prev = node;
}
head = node;
}
public void addLast(int val) {
Node node = new Node(val);
if (tail == null)
head = node;
else {
tail.next = node;
node.prev = tail;
}
tail = node;
}
private static final class Node {
private final int val;
private Node prev;
private Node next;
public Node(int val) {
this.val = val;
}
}
}
I am trying to reverse a linked list and return the new head.
public Node reverse(Node head) {
Node node = head;
if (node.next == null) {
head = node;
return head;
}
Node next = node.next;
reverse(next);
next.next = node;
return head;
}
Node class:
public class Node {
int data;
Node next;
}
With input 1 -> 2 -> 3 -> 4 -> 5 I get output 1 -> 2 -> 1 -> 2 -> 1. Why does it cycle through the first 2 nodes and leave out the remaining 3? Also, why has the new head not updated to node 5?
There are 2 problems:
you are not saving the new head once it is returned (when you reach the end of the list), so the returned head is always going to be the one of the first stack of recursion, which is the original first node;
you are not assigning node.next to null on the first node, so it will never become the new tail of the list.
This is the corrected code:
public Node reverse(Node head) {
Node node = head;
if (node.next == null) {
head = node;
return head;
}
Node next = node.next;
// fix for problem 2, we transform the current node in the tail
node.next = null;
// fix for problem 1, head is now the tail node
head = reverse(next);
next.next = node;
return head;
}
I solved the next exercises having two solutions: https://www.hackerrank.com/challenges/reverse-a-doubly-linked-list
First (non-recursive):
/*
Insert Node at the end of a linked list
head pointer input could be NULL as well for empty list
Node is defined as
class Node {
int data;
Node next;
Node prev;
}
*/
Node Reverse(Node head) {
if (head == null) return null;
Node current = head;
while (current.next != null) {
Node temp = current.next;
current.next = current.prev;
current.prev = temp;
current = temp;
}
current.next = current.prev;
current.prev = null;
return current;
}
Second algorithm (recursive):
/*
Insert Node at the end of a linked list
head pointer input could be NULL as well for empty list
Node is defined as
class Node {
int data;
Node next;
Node prev;
}
*/
Node Reverse(Node head) {
if (head.next == null) {
head.next = head.prev;
head.prev = null;
return head;
}
Node newHead = Reverse(head.next);
Node temp = head.next;
head.next = head.prev;
head.prev = temp;
return newHead;
}
According to the book, the solution must be O(n). I guess using recursive solution is more elegant but maybe I'm wrong. Can you help to determine the space and time complexity of these two algoritms, or in your, which is better in performance?
The question is a bit unclear, both solutions seem to be O(n) in both time and space. Although you could probably remove the special cases and make Torvalds happy. Something like:
Node Reverse(Node head) {
if (head == null) return null;
Node current = head;
while (current != null) {
Node temp = current.next;
current.next = current.prev;
current.prev = temp;
current = temp;
}
return current;
}
Node Reverse(Node head) {
Node temp = head.next;
head.next = head.prev;
head.prev = temp;
return temp==null?head:Reverse(temp);
}
I have not tested these, use them as inspiration only. (Also the recursive will nullpointer if head is null in the beginning).
I'm doing the problem on hacker rank on inserting node at specific position. Im using java in this case, but I keep getting an error. And I don't know how to fix it. I appreciate your help. Here is my solution:
/*`enter code here`
Insert Node at a given position in a linked list
head can be NULL
First element in the linked list is at position 0
Node is defined as
class Node {
int data;
Node next;
}*/
Node InsertNth(Node head, int data, int position) {
`enter code here`// This is a "method-only" submission.
// You only need to complete this method.
if(head == null){
Node newNode = new Node();
newNode.data = data;
newNode.next = null;
return head;
}
if(position == 1){
Node newNode = new Node();
newNode.data = data;
newNode.next = head;
head = newNode;
return head;
}
// we need to go to n - 1
int counter = 0;
Node currNode = head;
Node prevNode = null;
while(counter != position -1 && currNode.next != null){
prevNode = currNode;
currNode = currNode.next;
counter++;
}
Node nNode = new Node();
nNode.data = data;
prevNode.next = nNode;
nNode.next = currNode;
return head;
/* another solution */
}
Result:
Exception in thread "main" java.lang.NullPointerException
at Node.InsertNth(Solution.java:54)
at Solution.main(Solution.java:89)
In the code snippet that you have given, in comment you have mentioned that first element is at position 0. So in case insertion happens at position 0 then head will change. Thus the condition where you do
if(position == 1){
Node newNode = new Node();
newNode.data = data;
newNode.next = head;
head = newNode;
return head;
}
Yo should actually check position == 0. And the non stop repetition in your output that you are saying is because of this only. E.g if linked list 10->20 , I wish t insert 30 at position 0 , and we go by your code then we will not enter the loop as 0(counter) != -1 (position -1) so we prevNode and currNode both are pointing to 10 now and
Node nNode = new Node();
nNode.data = data;
prevNode.next = nNode; // you made 10 point to 30
nNode.next = currNode; // here you made 30 point to 10 so **loop** here
As far as I can see in the information you sent, the NullPointerException will happen if the flow don't get into the "while" loop, so the "prevNode" will remain null. Then you will get the exception in the "prevNode.next = nNode" line.
It will be easy to get if you debug the code.
Node class
private class Node<E> {
E data;
Node<E> next;
public Node(E obj) {
data = obj;
next = null;
}
}
insert method (ascending order)
public void insert(E obj) {
Node<E> newNode = new Node<E>(obj);
Node<E> prev = null, curr = head;
while(curr != null && ((Comparable<E>)obj).compareTo(curr.data) >= 0) {
prev = curr;
curr = curr.next;
}
if(prev == null)
head = newNode;
else {
prev.next = newNode;
newNode.next = curr;
}
currentSize++;
}
remove method
public E remove() {
if(isEmpty())
return null;
E tmp = head.data;
head = head.next;
currentSize--;
return tmp;
}
I get Null Pointer Exception at the line
E tmp = head.data;
in the remove method
The error is fixed if the change the else statement in my insert method to
else
prev.next = newNode;
newNode.next = curr;
There's a problem when you insert a new node that needs to go at the beginning of the list (because it's smaller than the current head node). When you get to this part:
if(prev == null)
head = newNode;
you're setting head to be the new node you've just created, but you also need to set newNode.next to be the previous head. So you really want
if(prev == null) {
newNode.next = head;
head = newNode;
}
which inserts the new node at the beginning but tacks the previous head onto it.
With your code as it stands, when you add a second element that should go at the beginning, you're accidentally discarding the element that's already there, but you're still increasing currentSize; so you end up with a list with only one element, but a currentSize of 2. When you then try to remove two elements, the second one fails with a NullPointerException because you try to read the data inside a non-existent element.