Flatten a Multilevel Doubly Linked List leetcode - java

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.

Related

Java: Understanding the Singly Linked List implementation

Consider I am trying to add 10, 20 & 30. When I am adding the first node 10, the HEAD will be null. At this point, both HEAD and TAIL will point to the same node i.e. 10. Now when adding the second node 20, we are updating the TAIL's next to point to node 20. Since HEAD and TAIL share the same reference, HEAD also gets updated. All cool till here. After this, we are updating the tail reference. Now HEAD and TAIL won't share the common reference, right? But still how the HEAD is getting updated when we are adding the third node? I am so confused understanding it...
public class LinkedList {
private class Node {
private int data;
private Node next;
public Node(int data) {
this.data = data;
}
}
private Node head;
private Node tail;
public void add(int data) {
var node = new Node(data);
if (head == null) {
head = tail = node;
return;
}
tail.next = node;
tail = node; // At this point, TAIL and HEAD are no longer connected, right? Still how HEAD gets updated when we are updating only TAIL?
}
}
tail = node;
// At this point, TAIL and HEAD are no longer connected, right?
the tail is the last element that you add it's normal to do tail = node; to change the old tail and in this case the head will be connected with the new tail.
//Still how HEAD gets updated when we are updating only TAIL?
after the first assign of the head it still the same during all the adds that we make inside the linkedlist
When you did tail = node, the tail reference is updated to where node is referring.
The head reference is still the same as what you set it the first time.

Why head node is not changing in printLL() 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.

How traversing from node to node is happened in a Linked list

I just started to learn the concept of Linked List recently, and have a problem on how the else statement works in the below code. How does it traverse to next node until a NULL value is found in the node?
public class LinkedList {
Node head;
public void insert(int data) {
Node node = new Node(data);
node.data = data;
if(head == null) {
head = node;
}else{
Node temp = head;
while(temp.next != null) {
temp = temp.next;
}
temp.next = node;
}
}
}
The Node class is the representation of a node in a linked list. Each Node has its own data and a pointer/reference to the next Node, which is stored in the next member of the Node class.
Now answering your question about traversal. We start the traversal from the head of the linked list - Node temp = head;. We now use a while loop to traverse the linked list and stop only when we reach the last Node in the linked list. The last node will have the next reference as null, hence the condition while(temp.next != null). Inside the loop, you are hopping to the next node and the loop will stop when you reach the last node. You then set the new Node as the next node of the last node in order to fulfill the data insertion function.

How a java class works with it's own reference type

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.

How can I implement append and deleteNode methods for a LinkedList implementation in Java?

I am improving my data structures skills. I am trying to implement a LinkedList from scratch.
This is what I have done so far:
class Node {
Node next = null; //reference to null
Object data; //value of the node
public Node(Object d) {
data = d; //constructor that assigns the node's value to the node
}
void append(Object d) {
Node end = new Node(d); //create the new node
Node n = this;
while (n.next != null) { //keep moving the reference until we reach null which is the reference of the last node
n = n.next;
}
n.next = end; //Assign the null reference to the node end which is the node to be added
}
Node deleteNode(Node head, Object d){
Node n = head; //Call the pointer to the head n;
if (n.data == d) { //Check if the data of the current node is same as node to be deleted
return head.next; //Here I got lost, I don't know why we're returning head.next
}
while (n.next != null) { //as long as we have reached the last node
if (n.next.data == d) {
n.next = n.next.next; //I don't get this
return head; //Why are we returning head
}
n = n.next;
}
return head;
}
}
The problem is I don't understand the deleteNode method. I have found it in the book Cracking the Code interview. Could someone please clarify for me what is actually happening? The whole reference thing is getting me confused.
The deleteNode method seems to return the linked list. Here's what it does:
If the first element of the linked list is the item that we seek (its data matches d), then we just return the list starting from the second element (head.next). There's nothing linking back to that first element, so the first element is gone. Just what we wanted.
Look through all nodes. They do this by looking at n.next. If its data matches d, then this node should be removed. So then let the list skip that element: Set n.next to be n.next.next (which is the element after it) rather than the element that matched d.
Normally these kinds of methods tend to return the element that was removed. Instead, this seems to return the list itself, which is represented by its head. That's why the method keeps returning head.

Categories

Resources