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;
}
Related
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;
}
}
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'm trying to write a single function in Java (Node sortedmerge(Node node1, Node node2)) where the data in node1 and node2 are already sorted in descending order ({5, 3, 1, 0}). I figured out an implementation for the function but I can't figure out how to make it recursive:
//Defined elsewhere as a global variable
static Node<Integer> head = new Node();
//Used to store the final sorted linked list
Node sortedmerge(Node node1, Node node2) {
// if both the nodes are null
if (node1 == null && node2 == null) {
return null;
}
// if both of them have nodes present traverse them
while (node1 != null && node2 != null) {
// Now compare both nodes current data
if (node1.data <= node2.data) {
Node temp = node1.next;
node1.next = head;
head = node1;
node1 = temp;
} else {
Node temp = node2.next;
node2.next = head;
head = node2;
node2 = temp;
}
}
// If second list reached end, but first list has
// nodes. Add remaining nodes of first list at the
// front of result list
while (node1 != null) {
Node temp = node1.next;
node1.next = head;
head = node1;
node1 = temp;
}
// If first list reached end, but second list has
// node. Add remaining nodes of first list at the
// front of result list
while (node2 != null) {
Node temp = node2.next;
node2.next = head;
head = node2;
node2 = temp;
}
return head;
}
supposedly there's a way to do it without a temporary node (Node temp) or any outside functions... but at this point I'd just be happy to make it function recursively (I'm struggling to understand how to implement recursive calls).
Your function merges two sorted lists, you can implement this with a loop as posted or recursively as will be shown below. Note however that:
there is no reason to make head a global variable. You should instead define it as a local and return as the return value of the function.
the head in your code does not point to the head of the list, but to the last element, aka the tail node.
once one of the lists is exhausted, you can just append the other to the last element of the merged list.
a recursive implementation of sortedmerge will require stack space proportional to the length of the merged list, which can easily exceed available stack space, causing a stack overflow exception.
Here is a simple recursive implementation:
Node sortedmerge(Node node1, Node node2) {
// if either node is null, return the other node
if (node1 == null) {
return node2;
}
if (node2 == null) {
return node1;
}
// select the node with the largest data
if (node1.data <= node2.data) {
// select node2 and append the rest of the merged list to it
node2.next = sortedmerge(node1, node2.next);
return node2;
} else {
// select node1 and append the rest of the merged list to it
node1.next = sortedmerge(node1.next, node2);
return node1;
}
}
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).
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;
}