I was coding on gfg practice to test whether a linked list is a palindrome, and after I reversed the linked list, it showed only one node.
This is the code below (the linked list passed is 1->2->1) :-
class Solution
{
//Function to check whether the list is palindrome.
boolean isPalindrome(Node head)
{
Node temp=head;
Node reversed= reverseList(temp);
Node cur = head;
while(cur!=null)
{
System.out.println(cur.data+" inloop");
cur=cur.next;
}
return true;
}
Node reverseList(Node node)
{
Node prev = null;
Node current = node;
Node next = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
node = prev;
return node;
}
}
The output of this code is ( the linked list passed is 1->2->1) : -
1 inloop
But if I comment out the Node reversed = reverseList(temp); line, the output is as expected: -
1 inloop
2 inloop
1 inloop
Where is my mistake?
When the list is reversed, the previous head of the list has become the tail. Concretely, after that reversal, head references the tail of the now reversed list. A tail has (by definition) a next member that is null, and so your while loop will only iterate once.
Realise that when you reverse the list, you don't have the original order anymore: all next members have lost their original value and now (only) have a reference that reflects the reversed order.
You have a few options to do it right:
Have your reverse method create a new list, so that caller will then have both the original and the reversed list. This will allow you to iterate both lists in tandem and compare the node values as intended
Create an array from the list. Now check whether the array is a palindrome.
The above options need O(n) extra space. You can solve this without O(n)
auxiliary space: only reverse half of the list. Here you don't need to create new nodes, but by only reversing half of the list, you can traverse the reversed part and the non-reversed part in tandem and make value comparisons
Related
You are given a doubly linked list which in addition to the next and previous pointers, it could have a child pointer, which may or may not point to a separate doubly linked list. These child lists may have one or more children of their own, and so on, to produce a multilevel data structure, as shown in the example below.
Flatten the list so that all the nodes appear in a single-level, doubly linked list. You are given the head of the first level of the list.
class Solution {
/*Global variable pre to track the last node we visited */
Node pre = null;
public Node flatten(Node head) {
if (head == null) {
return null;
}
/*Connect last visted node with current node */
if (pre != null) {
pre.next = head;
head.prev = pre;
}
pre = head;
/*Store head.next in a next pointer in case recursive call to flatten head.child overrides head.next*/
Node next = head.next;
flatten(head.child);
head.child = null;
flatten(next);
return head;
}
}
For the question, the above leetcode solution works. But I don't understand this:
/*Store head.next in a next pointer in case recursive call to flatten head.child overrides head.next*/
Node next = head.next;
Can anyone explain this part? How does the head.child override head.next?
flatten(head.child) may change head.next due to the part where we connect last visited node with the current node:
if (pre != null) {
pre.next = head;
head.prev = pre;
}
At this stage, pre represents older head and head represents head.child. So we actually connect our head with its child. But if we do so, we will lose our connection to the actual head.next, therefore we have to keep it in an extra variable called next. That's why we keep it before calling the flatten() function.
I am trying to print a linked list. Both head and node are references of each other but still, the head is not changing after while loop in printLL() function. After end of while loop node is null but head is still pointing to 10. Why this is happening?
class Node {
int data;
Node next;
Node(int value) {
this.data = value;
this.next = null;
}
}
class LL {
Node head;
void createLL() {
head = new Node(10);
head.next = new Node(20);
head.next.next = new Node(30);
head.next.next.next = new Node(40);
}
void printLL() {
Node node = head;
System.out.println("Printing full Linked List");
while (node != null) {
System.out.println(node.data);
node = node.next;
}
System.out.println("Value of head is " + head.data);
if (head.equals(node)) {
System.out.println("head and node both are same");
}
else {
System.out.println("head and node are not same");`
}
}
}
// Output -
// Printing full Linked List
// 10
// 20
// 30
// 40
// Value of head is 10
// head and node are not same
What is a Linked List ?
A linked list is formed by nodes that are linked together like a chain. Each node holds data, along with a pointer to the next node in the list.
The following image shows the basic structure of a Singly Linked List.
As you can see the Singly Linked List contains a head node: a pointer pointing to the first element of the list. Whenever we want to traverse the list, we can do so by using this head node.
Now using the below method of createLL(), you have created a linked list,
void createLL() {
head = new Node(10);
head.next = new Node(20);
head.next.next = new Node(30);
head.next.next.next = new Node(40);
}
This can be represented using an image as below for easier understanding,
So in the createLL method you have now created a linked list like
10->20->30->40->null
here the first node which is also called as the "head node" contains the data 10.
Now inside the method printLL(), the first line is as below,
Node node = head;
Here you created a temporary node named "node" and assigned it to value of head. The head contains the information of the next node and the next node contains the information of its next node and so on. So now using your temporary node "node" and assigning it the value of headnode, you can traverse the whole linked list you created via the method createLL().
And in the while loop below,
while (node != null) {
System.out.println(node.data);
node = node.next;
}
You have now traversed the linked list one by one until it reached to null. Remember the last node of a linked list always points to null. This while loop did not reassign the value/data of any nodes. But it just iterated from the first node till it reached the lastnode using a temporary node called "node". And the while loop finally assigns the "node" variable to null.
So in the if loop comparison,
if (head.equals(node))
you are comparing,
if(10.equals(null)
which will return as false, since headnode still pointing to the 10 itself. only the temporary node "node" is pointing to the null which does not affect the headnode or any node of the linked list you have created.
As we know, to push an element at the front of list requires O(1) time. Now consider we want to put (or append) an element at the end of list. What is the complexity of this operation?
Now consider, to put an element at the end of list, we need to traverse the list up to the end (because of not having prev. pointer), requires O(n) time complexity. Will it possible to make this in O(1)?
I did some implementation, while appending value at the end, I am keeping the next place in pointer, where node can be inserted. Check out the following please:
import java.util.*;
class List{
int data;
List next;
List(int data){
this.data = data;
}
}
class Driver{
List head, temp;
Driver(){
head = null;
temp = head;
}
void push(int item){
if(head == null){
head = new List(item);
temp = head;
} else {
temp.next = new List(item);
temp = temp.next;
}
}
}
class AppendInList{
public static void main(String [] args){
Driver obj = new Driver();
obj.push(5);
obj.push(66);
}
}
I searched in SO, but I didn't get anything for my satisfaction! Correct me if I did some mistake!
You can push an element to the front of a linked list in O(1) time, if you save a reference to the front/head element in the linked list data structure.
Similarly, you could maintain a reference to the last element, using which you could add an element to the last in O(1) time. You would have to update the last pointer every time you add an element.
The data structure could look like below:
class List{
ListNode head;//ListNode class stores next reference and value of the node
ListNode tail;//last element
void pushToLast(ListNode newElement){
//TODO : Take care of corner cases
tail.next = newElement;
tail = newElement;
}
}
Just started learning nodes and I have a few questions. Let's say I have a node class that looks like this:
private E number;
private Node next;
/**
* Constructor
*/
Node(E e){
number = e;
next = null;
}
and I have a series of linked nodes with the starting node named first like so:
first->(1)->(2)->(3)->(5)->(6)
Assuming the list is not empty, to traverse the list, I would do something like so:
Node curr = first;
while(curr != null){
System.out.print(curr);
curr = curr.next;
}
I understand that you cannot traverse a link list like this backwards, so does this mean that whenever I call curr.next the previous elements are just lost?
I was also wondering if first, my original list, will ever be affected by a temporary node list like curr? For example, if I was to insert or delete a node on the list with codes similar to these:
Insert:
Node curr = first;
Node newNode = new Node(4);
while(curr != null){
if(curr.number == 3){
newNode.next = curr.next;
curr.next = newNode;
}
curr = curr.next;
}
Delete:
Node curr = first;
Node parent = first;
while(curr != null){
if(curr.number == 3){
parent.next = curr.next;
}
parent = curr;
curr = curr.next;
}
Would the above code modify first or would I have to set first = curr; after the insertion or deletion for the changes take place? If they do modify first, how come curr = curr.next; doesn't modify first? What if I wanted to return the deleted node? Would I just do something like curr.next = null; and then return curr;?
does this mean that whenever I call curr.next the previous elements are just lost?
As you traversed down the list, you never modified first and you never modified the next link of any Node. So no node is ever really lost. Previously visited nodes just become a bit less convenient to access because you don't have a "handle" on them, but you could always find them again by starting back at the head of the list (first) and following the next links.
I was also wondering if first, my original list, will ever be affected by a temporary node list like curr?
The variable first will never be affected by anything other than an assignment statement having first on the left-hand side of the =. On the other hand, the list to which first refers might change quite dramatically or be completely unaffected, depending on what you are using curr for, but first itself can only be affected by assigning a new value to first.
Would the above code modify first or would I have to set first = curr;
The insert and delete code, as given, never modifies first. But it should, if it is going to be able to handle inserting a new node before the current first node, or deleting the current first node. Maybe not with first = curr specifically, but first will definitely need to be updated to reflect a new head of the list. I leave that, as the textbooks say, "as a exercise for the reader".
I'm fairly new to JAVA and OOP and I'm currently following an academic course where I'm learning data structures and algorithms in java.
As I was learning about implementation of linked lists I've ran into a small problem of not understanding the code how to create a node when implementing a linked list(I'm familiar with constructors and bit of recursion ).
Code of the Node class as follows
public class Node {
public int info;
public Node next, prev;
public Node (int el) {
this (el,null,null);
}
public Node (int el,Node n,Node p){
info = el; next =n; prev=p;
}
}
I need to know what's happening behind the scene when the code executes(especially how the line3 works)and code of the List class is as follows
public class List {
private Node head, tail;
public List ( ){
head = tail = null;
}
public boolean isEmpty( ){
return head == null;
}
public void addToTail (int el) {
if (!isEmpty ( )) {
tail = new Node (el, null, tail);
tail.prev.next = tail;
}
else head = tail = new Node(el);
}
public int removeFromTail ( ){
int el = tail.info;
if (head == tail)
head = tail =null;
else
{
tail = tail.prev; tail.next = null;
}
return el;
}
}
(This example is given by the academy where I'm learning and I want to know how it works)
Please explain how the Node class works.
Ok let's start from the Node Class
public Node next, prev;
public Node (int el) {
this (el,null,null);
}
Here the objects next and prev are references to the next and previous nodes to the current node (which is your current object (this))
this (el,null,null);
It means you are creating a node which has no previous or next node. as you pass null, null for next and previous. Its similar to creating a head as head doesn't have next and previous nodes.
When you create the head you will never change it but you will change the next of the head the time when you create the second element in your list
When you create a tail of the linked list
public void addToTail (int el) {
if (!isEmpty ( )) {
tail = new Node (el, null, tail);
tail.prev.next = tail;
}
else head = tail = new Node(el);
}
here you first create a tail Node by tail = new Node (el, null, tail);
And then get the previous of tail and set the next element of the prev as the tail by doing tail.prev.next = tail;
Every time you add a new Node to the list you are calling addToTail(int e1) which updates the tail and updates the next of the old tail.
Let's suppose the entry point of your code is a call to:
List list = new List();
list.addToTail(1);
list.addToTail(2);
list.removeFromTail();
The first line of code execute the constructor into the list class, which simply set head and tail equal to null.
The second line of code add the method addToTail, and set the variable head and tail equal to new Node(1), which invoke the constructor having one parameter only in the Node class.
The third line of code add the method addToTail, but this time the list is not empty, so the script enters in the if statement and the node that you save with Node(2, null, tail). If you check this Node constructor with three parameters, tail (the node you added before which value was 1) will be set as the prev (previous) node associated with the current one.
The last line of code remove the 2nd node with the code tail = tail.prev; tail.next = null; and return the element you just removed.
firstly node in java its a specific type of variable, which can do the normal work of a variable and have an other information allow her to point on an other node in your case is public Node next, prev;
usually node are used in list ,think like train this is why you have addtootail here or removefromtail .
in this link you find a pretty quite explanation about that.
http://www.vias.org/javacourse/chap14_02.html
The Node class encapsulates the data, in this case an integer value named info.
Also, the List is implemented as a sequence of Nodes.
The reason for the next and prev values in Node is so that the node can be linked to its previous and next nodes in the list sequence. The only way to access a node in the list is to traverse the list, either forwards using the next reference, or backwards using the prev reference.
Note that lists do not support random access like an array would. To get to an element, you need to traverse the list in some direction.
I need to know what's happening behind the scene when the code executes(especially how the line3 works).
Please explain how the Node class works.
public Node next, prev;
Java variables that refer to object types are references, not values. The fields next and prev are not Node objects. No Node object contains other Nodes. Instead, next and prev reference Node objects stored separately.
If you're coming from C or C++, you can think of these references somewhat like pointers.
EDIT:
If you're instead asking about the construction of linked lists in general, your Node class represents a single node, containing a single item, in a doubly linked list. In a doubly linked list, each node refers to the node before and the node after.
See this illustration of a doubly linked list in this related wikipedia article.
The List is like a train. A Node is like a car in the train. The links are references between Nodes, which are similar to the coupling between train cars. The next and prev fields that you ask about are the links between nodes.
Logically, the List contains the entire train. Physically, your List references the head and tail of the train, so that it can travel over the Nodes from front-to-back, or back-to-front.