I am learning linked list here https://practice.geeksforgeeks.org/problems/linked-list-insertion/1#
https://www.geeksforgeeks.org/linked-list-set-2-inserting-a-node/?ref=lbp
Here I have to write 2 functions to add a node at the beginning/the end of a linked list.
LinkedList: 9->0->5->1->6->1->2->0->5->0
The output should be: 5 2 9 5 6
But my output is: 5 2 9
I think I am wrong in the function add a node at the end, but I could not find my mistake. Could you please let me know where I am wrong?
Create a link list of size N according to the given input literals.
Each integer input is accompanied by an indicator which can either be
0 or 1. If it is 0, insert the integer in the beginning of the link
list. If it is 1, insert the integer at the end of the link list.
Hint: When inserting at the end, make sure that you handle NULL
explicitly.
Example 1:
Input:
LinkedList: 9->0->5->1->6->1->2->0->5->0
Output: 5 2 9 5 6
Explanation:
Length of Link List = N = 5
9 0 indicated that 9 should be
inserted in the beginning. Modified
Link List = 9.
5 1 indicated that 5 should be
inserted in the end. Modified Link
List = 9,5.
6 1 indicated that 6 should be
inserted in the end. Modified Link
List = 9,5,6.
2 0 indicated that 2 should be
inserted in the beginning. Modified
Link List = 2,9,5,6.
5 0 indicated that 5 should be
inserted in the beginning. Modified
Link List = 5,2,9,5,6.
Final linked list = 5, 2, 9, 5, 6.
Here is my solution:
class Solution
{
//Function to insert a node at the beginning of the linked list.
Node insertAtBeginning(Node head, int x)
{
// code here
Node current = new Node(x);
current.next = head;
head = current;
return head;
}
//Function to insert a node at the end of the linked list.
Node insertAtEnd(Node head, int x)
{
// code here
Node current = head;
while(current.next != null){
current = current.next;
}
Node addthis = new Node(x);
current = addthis;
return head;
}
}
Indeed there is an issue in your insertAtEnd() method. You correctly iterate through to the tail of your linked list, but your problem is here:
current = addthis;
This will simply assign your new node to current, which is not what you want.
What you want is, to attach your new node to the next field of your last node like this:
current.next = addthis;
This way, you actually added your node to the previously last element of the list.
Full code:
Node insertAtEnd(Node head, int x) {
Node current = head;
while(current.next != null){
current = current.next;
}
Node addthis = new Node(x);
current.next = addthis;
return head;
}
class Solution {
//Function to insert a node at the beginning of the linked list.
Node insertAtBeginning(Node head, int x) {
Node node = new Node(x);
if (head == null) {
head = node;
return head;
}
node.next = head;
head = node;
return head;
}
//Function to insert a node at the end of the linked list.
Node insertAtEnd(Node head, int x) {
Node node = new Node(x);
if (head == null) {
head = node;
return head;
}
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = node;
return head;
}
}
Related
My goal is to loop backwards through a list I have created and if an element is smaller than my chosen number t a node with the value of t will be inserted in front of the element that is smaller. Also, if every element in the list is bigger than t a node with the value of t will be put at the start of the list. Example:
DoublyLinkedList<Integer> list = new DoublyLinkedList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.addAtFirstSmaller(4);
System.out.println("Nodelist: " + list.toString());
And I should expect the outcome:
[1, 2, 4, 3, 4, 5]
But instead I get:
[1, 2, 3, 4, 4, 5]
This is my code so far:
public void addAtFirstSmaller(T t)
{
ListNode<T> node = tail;
ListNode<T> newNode = new ListNode<T>(t);
while(node.previous != null)
{
int compared = node.previous.element.compareTo(t);
node = node.previous;
if(compared < 0)
{
ListNode<T> temp = node.next;
node.next = newNode;
newNode.next = temp;
newNode.next.previous = newNode;
node.previous = null;
size++;
}
else if(compared > 0 && node.previous == null)
{
addFirst(t);
size++;
}
}
}
To me it seems like everything is pushed to the right. Any idea on what to do?
As you already verified: the example output is correct as the idea is to maintain the list sorted. The misinterpretation was understandable, as "in front of" is somewhat ambiguous.
However, there are still a few issues with your code:
Although the assignment node.previous = null will make the loop end once you have inserted the new node, this breaks a previous link that really should remain untouched. Only the head node should have previous equal to null, while in general node could have a predecessor, which must remain its predecessor.
newNode.previous never receives a value. It should be set to node.
When the value to insert is greater than the value in the tail node, the node will be inserted at the wrong spot -- there is never a scenario in your code where the new node will become the new tail, yet this is a possibility that should be foreseen.
I would assume that addFirst would already increase size, so increasing it again after you call this function is wrong. This really should be the responsibility of addFirst.
Assuming that you have implemented addLast, the corrected code could be like this:
public void addAtFirstSmaller(T t) {
ListNode<T> node = tail;
ListNode<T> newNode = new ListNode<T>(t);
while (node != null && node.element.compareTo(t) >= 0) {
node = node.previous;
}
if (node == null) {
addFirst(t);
} else if (node == tail) {
addLast(t);
} else {
ListNode<T> temp = node.next;
node.next = newNode;
newNode.next = temp;
newNode.previous = node;
temp.previous = newNode;
size++;
}
}
In case you don't have it yet, addLast could look like this:
public void addLast(T t) {
ListNode<T> newNode = new ListNode<T>(t);
tail.next = t;
t.previous = tail;
tail = t;
size++;
}
I just received an answer from my instructor, and it seems like my output is correct ([1, 2, 3, 4, 4, 5] that is). I will mark this thread as closed as the code is working.
I have added an element to a specified position in a Doubly Linked List, but I want to shift all the elements that was at that position and after it to the right? Any tips on how to approach this problem?
public void addFirst(E e){
DNode<E> headerNext = header.getNext();
DNode<E> tempN = new DNode <E>(e, header, headerNext);
headerNext.setPrev(tempN);
header.setNext(tempN);
size++;
}
public void add(int pos , E e ){
DNode<E> ptr = new DNode<E> (e, null, null);
if(pos == 1){
addFirst(e);
return;
}
DNode<E> optr = header;
for (int i = 2; i <= size; i++) {
if (i == pos) {
DNode<E> tempN = optr.getNext();
ptr.setNext(ptr);
ptr.setPrev(optr);
ptr.setPrev(tempN);
tempN.setPrev(ptr);
}
ptr = ptr.getNext();
}
size++ ;
}
}
Based example in your comment:
You need to update the next pointer of new node to point to element 3's address
Element 3's previous pointer to new node address
New node previous address with element 3's previous address
Lastly Goto element 3's previous address(node) and update its next pointer to new node address.
Any tips on how to approach this problem?
Since you asked for tips on how to get started and you already have a doubly linked list here is a simple example.
Given the following is a Node in a Doubly Linked 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; }
}
The following method can be implemented for your doubly linked list. You would provide a Node that would have a new Node inserted after the Node that you provide and the next and prev pointers for the current Node and the newly added Node would all be updated to reflect the newly added Node.
/* Given a node (currentnode). insert a new node after the given
node(currentNode) */
public void InsertAfterNode(Node currentNode, int newData)
{
// check if the given current node is NULL
if (currentNode == null) {
System.out.println("The given current node cannot be NULL ");
return;
}
// allocate node
// put in the data
Node new_node = new Node(newData);
// Make next of new node as next of current node
new_node.next = currentNode.next;
// Make the next of current node as new_node
currentNode.next = new_node;
// Make current node as previous of new_node
new_node.prev = currentNode;
// Change previous of new_node's next node
if (new_node.next != null)
new_node.next.prev = new_node;
}
You could implement a similar method, in reverse, to insert a new Node before the specific Node.
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'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.
I'm writing a method called twin() that would take a linked list [1 2 3 4] and return [1 1 2 2 3 3 4 4]. I have a working method but I'm confused about a part. In my code, i declare a new SListNode variable called temp. I want this temp to copy the current node and then connect it. When I try to do SListNode temp = current, the program won't run. However, if I manually set temp's item and next fields, the method will run just fine. Can anyone explain what happens when you do SListNode temp = current please?
public void twin() {
SListNode current = head;
if(current == null){
return;
}
for(int i = 0; i <this.length();i++){
if(current == null){
return;
}
SListNode temp = new SListNode(0); // Problem here when I substitute these 3 lines for SListNode temp = current;
temp.next = current.next;
temp.item = current.item;
current.next = temp;
current = current.next.next;
}
}
If you did temp = current, you won't copying the object. You will be just giving another way to access to that object. In other words, temp and current will be referring to the same object.
If you did that, the lines
temp.next = current.next;
temp.item = current.item;
won't do anything, because it will be like doing temp.next = temp.next.
Also, in the line
current.next = temp;
you would be making current's next node to be itself (current.next will be current).