I am trying to learn to insert a node in a linked list (and return the head), but for some reason it is not correct.
This is my approach:
1. Create the new node with the desired data
2. If we want to insert it in the beginning, point this new node to the head and return the new node
3. Otherwise, loop to the position where we want to insert the node
- Once we get there, point the node to be inserted's next to the current node's next
- Point the current node to the node to be inserted
- Return the head
Why does this not work? Thanks so much!
Node InsertNth(Node head, int data, int position) {
Node node = new Node();
node.data = data;
if (position == 0) {
node.next = head;
return node;
}
else {
Node curr = head;
int currPos = 0;
while (currPos < position) {
curr = curr.next;
currPos++;
}
node.next = curr.next;
curr.next = node;
}
return head;
}
Given that you insert the new node after the curr node, this loop steps one node too far.
while (currPos < position) {
curr = curr.next;
currPos++;
}
You can easily work this out by stepping through through the code with a pen and paper, or with a debugger.
If you insert the node to the Head you need to set the Head to the node you're inserting.
Node InsertNth(Node head, int data, int position) {
Node node = new Node();
node.data = data;
if (position == 0) {
node.next = head;
head = node;
}
else {
Node curr = head;
int currPos = 0;
while (currPos < position) {
curr = curr.next;
currPos++;
}
node.next = curr.next;
curr.next = node;
}
return head;
}
Related
I am currently working on a linked list that need to insert and delete data from the position that user input. However, I have met some error with insertion. I follow the code that I found online and I don't know where is the problem, the data that I enter did not insert to the linked list, everytime I display the linked list it shows me NULL even I do have insert some data in it.
Here is my code for insertion:
public void addItemRequest(Node head, int item, int position)
{
Node prevNode = head;
Node newNode = new Node(item,null);
if (head==null)
{
return;
}
if (position == 0)
{
newNode.next = head;
return;
}
int count = 0;
while (count < position -1 && head.next != null)
{
head = head.next;
count++;
}
Node currNode = head.next;
head.next = newNode;
head = head.next;
head.next = currNode;
return;
}
Here is my code for Node class:
class Node{
int num;
Node next;
Node()
{
num=0;
next=null;
}
Node(int num, Node next)
{
this.num=num;
this.next=next;
}
int getNum()
{
return num;
}
Node getNext()
{
return next;
}
void setNext(Node next)
{
this.next=next;
}
}
I hope someone could tell me what is the problem here, thanks.
You have to make head as a global variable then only it will work
Go easy with only one temp node that is new
public void addItemRequest(Node head, int item, int position)
{
Node prevNode = head;
Node newNode = new Node(item,null);
if (head==null)
{
head=newNode;
return;
}
if (position == 0)
{
newNode.next = head;
head = newNode;
return;
}
int count = 0;
while (count < position -1 && head.next != null)
{
prevNode = prevNode.next;
count++;
}
newNode.next = prevNode.next;
prevNode.next = newNode;
return;
}
Check now. I have corrected the answer. head=newNode; has to added in if (position == 0)
If you really want to appreciate accept the answer and upvote it. So that someone like you can also find the solution easily.
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 am trying to implement the reverse function of my own LinkedList implementation. Using my implementation of LinkedList:
public class LinkedList<T> {
public Node head;
public LinkedList(){
// Add HEAD
head = new Node(null);
}
public void add(T data){
getLastNode().next = new Node(data);
}
public void insert(int index, T data){
if(index == 0){
throw new Error(); // TODO: What is the Error Type?
}
Node current = head;
for (int i = 0; i != index - 1 ; i ++) {
current = current.next;
if (current == null){
throw new IndexOutOfBoundsException();
}
}
Node next = current.next;
Node newNode = new Node(data);
current.next = newNode;
newNode.next = next;
}
public T get(int index){
return getNode(index).data;
}
public void delete(int index){
if (index == 0){
throw new IndexOutOfBoundsException("Cannot delete HEAD node");
}
Node prev = getNode(index - 1);
Node next = prev.next.next;
prev.next = null;
prev.next = next;
}
public void reverse(){ // TODO: Last node links to a null node
Node prev = null;
Node current = head;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head = new Node(null);
head.next = prev;
}
public void display(){
Node current = head;
String diagram = String.format("head->");
while(current.next != null){
current = current.next;
diagram += String.format("%s->", current.data);
}
System.out.println(diagram);
}
private Node getNode(int index){
Node node = head;
for(int i = 0; i != index; i++){
node = node.next;
if(node == null){
throw new IndexOutOfBoundsException();
}
}
return node;
}
private Node getLastNode(){
Node current = head;
while(current.next != null){
current = current.next;
}
return current;
}
public class Node {
private Node next;
private T data;
public Node(T data){
this.data = data;
}
public Node getNext(){
return this.next;
}
}
}
And this main function:
LinkedList list = new LinkedList();
list.add("e1");
list.add("e2");
list.add("e3");
list.add("e4");
list.display();
list.reverse();
list.display();
The displayed result is:
head->e1->e2->e3->e4->
head->e4->e3->e2->e1->null->
This has happened due to the fact that e1 is still connected to the head. If I use the implementation of reverse available online:
Node prev = null;
Node current = head;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head = prev;
Then the result will ditch e4: head->e3->e2->e1->null->
What am I doing here? Why is my implementation different than everybody else's?
Also: Why does everyone use a reverse function that has head as an argument which could be problematic if the developer enters a different node?
You are using a first node as a head of your list. The solution for the reverse function is this:
head.next = prev;
You have to preserve the 'head' node, but change its 'next' field.
The rest of the function don't change at all:
public void reverse(){ // TODO: Last node links to a null node
Node prev = null;
Node current = head.next;
Node next = null;
while(current != null){
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head.next = prev; // *** The only change ***
}
In your constructor you have:
public LinkedList(){
// Add HEAD
head = new Node(null);
}
then, 'head' is a Node that points to nothing initially.
In the reverse function, the 'head' node don't change, you don't need to create another out. But it has to point to the correct first Node.
If the list was empty, this 'head' points to null.
If the list has only one Node, this 'head' points to it yet.
If the list has more than one Node, this 'head' has to point to the last node.
Because of this, you need to change its 'next' field.
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.
public void insertElementBefore(E element, E newElement) {
MyNode<E> current = head;
if (head != null) {
while (current != null) {
if (current.data.equals(element)) {
MyNode<E> n = new MyNode<E>(newElement);
n.next = current.next;
current.next = n;
return;
}
current = current.next;
}
}
}
This is what I have for this. I'm having troubles to insert the newElement before intended element. Can't seem to figure out the syntax for it. I've been tinkering with it for a while and the best I could get was for it to insert after the element like it currently does
Any help would be greatly appreciated
In case of a single linked list, you will need two temporary nodes:
MyNode<E> current that will represent the current node in the single linked list.
MyNode<E> prev that will represent a node before the current node in the single linked list.
Then, you have to add the new node between these nodes. If you don't have the prev node, then when setting the current node as the next node of the new node, then all the nodes before current will be lost.
This is how your code would look like:
public void insertElementBefore(E element, E newElement) {
MyNode<E> current = head;
//check here
MyNode<E> prev = null;
if (head != null) {
while (current != null) {
if (current.data.equals(element)) {
MyNode<E> n = new MyNode<E>(newElement);
n.next = current;
//check here
if (prev != null) {
prev.next = n;
}
return;
}
//check here
prev = current;
current = current.next;
}
}
}
The trick is to memorise the previous node.
MyNode<E> current = head;
MyNode<E> previous = null;
while (current != null && !current.data.equals(element)) {
return;
}
previous = current;
current = current.next;
}
MyNode<E> n = new MyNode<>(newElement);
n.next = current;
if (previous == null) {
head = n;
} else {
previous.next = n;
}
void Insert_Before(int num)
{
Node *x=new Node();
x->data=num;
if (head==NULL) {
x->next=head;
head=x;
} else {
int c=1;
cout<<"Element before which insertion has to take place:";
cin>>n;
Node *temp=head;
Node *temp1;
//check whether the element is present or not
while (temp->data!=n) { //if present
temp=temp->next;
c=c+1; //finds the position of the element n
}
x->next=temp;
if (c==1) {
head=x;
} else {
int i=1;
while (i<=c-1) {
temp1=temp1->next;
i=i+1;
}
temp1->next=x;
}
}
} //Insert_Before
Node n=headNode;
Node prev=null;
while(n!=null){
if(n.getData()==node){
Node newNode=new Node(data);
prev.setNext(newNode);
newNode.setNext(n);
break;
}
else{
prev=n;
n=n.getNext();
}
}
if(n.getNext()==null){
Node newNode= new Node(data);
prev.setNext(newNode);
newNode.setNext(null);
}
System.out.println("New LinkedList after insert before is:");
printList();
}
Create a new node called previous-node, and keep track of current element. In my code, if the current element matches the value of the node variable, we add a new node before it.