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.
I'm learning data structures and try to understand Linked lists in Java. My problem is that i have troubles with deleting nodes at a given index recursively. My goal is to get O(log n) instead of using loops and end up with O(n).
public class LinkedList {
Node head;
int index=0;
Node temp;
Node prev;
public LinkedList(Node head){
this.head=head;
temp=head;
prev=null;
}
public int length(){
int counter=0;
Node n= head.next;
while(n!=null){
counter=counter+1;
n=n.next;
}
return counter;
}
public void push(Node newNode){
newNode.next=head;
head=newNode;
}
public void add(Node prevNode, int value){
if(prevNode==null){
System.out.println("The given previous node can not be null!");
return;
}
Node newNode= new Node(value,null);
newNode.next=prevNode.next;
prevNode.next=newNode;
}
public void add(int index, int value){
length();
if((index<0)||(index>length())){
System.out.println("Array out of bound!");
return;
}
if(index==0){
push(new Node(value,null));
return;
}
Node newNode= new Node(value,null);
Node prevNode=head;
for(int i=1;i<index;i++){
prevNode=prevNode.next;
}
newNode.next=prevNode.next;
prevNode.next=newNode;
}
public void delete(){
head=head.next;
}
public void delete(int index){
if((index<0)||(index>length())){
System.out.println("Array out of bound!");
return;
}
if(index==0){
delete();
return;}
if(head.next==null||head==null){
head=null;
return;}
if(this.index!=index){
this.index++;
prev=temp;
temp=temp.next;
delete(index);
}if(this.index==index){
prev=temp.next;
}
}
public void search(int value){
if(head!=null){
if(value!=head.value){
head=head.next;
index=index+1;
search(value);
}else if(value==head.value){
System.out.println("The value \""+value+"\" was found in index: "+index);}}}
public void display(){
Node n= head;
System.out.print("{");
while(n!=null){
System.out.print(" ("+n.value+") ");
n=n.next;
}System.out.print("}");
System.out.println("\n------------------------------");
}
public static void main(String[]args){
LinkedList ll= new LinkedList(new Node(2,null));
ll.push(new Node(5,null));
ll.push(new Node(6,null));
ll.push(new Node(13,null));
ll.push(new Node(1,null));
ll.display();
ll.add(ll.head.next,8);
ll.display();
ll.add(0, 0);
ll.display();
ll.add(6, 4);
ll.display();
System.out.println(ll.length());
ll.search(13);
ll.delete(2);
ll.display();
}
}
So when i'm trying to delete the entry at the index 2, it deletes all the digits before that index but not at that index - so it deletes [0] and [1] but not [2].
For example in this code, the array before deleting is filled with: {0,1,13,8,6,5,4,2}.
After calling delete(2), it has the following entries: {13,8,6,5,4,2}
All what i want is to delete only the 13, so that the array would look like this: {0,1,8,6,5,4,2}
I would really appreciate any tips to improve my code.
It was very difficult to understand your code, but as you asked for logic to improve your understanding, so sharing psuedocode, which you could refer to correct your code accordingly.
Node delete (index i, Node n) // pass index and head reference node and return head
if (n==null) // if node is null
return null;
if (i==1) // if reached to node, which needs to be deleted, return next node reference.
return n.next;
n.next= delete(n.next,i-1);
return n; // recursively return current node reference
A Java recursive delete method in a linked list
Ok, let's go through this with an example. It's simplistic, but once you get the hang of it and understand the delete recursion algorithm, you can easily make the sample classes generic, take care of encapsulation, optimize the code and then go on to production.
Classes in this example
Assume, for the sake of example, that the basic Singly LinkedList and Node classes are very simplistic. The inner static Node class only stores primitive int types and it only includes a next reference to the following Node element in the list. The LinkedList only includes a head node, which is the beginning of the linked list. This is not a doubly linked list and it does not have a reference to the previous node. Traversals are done sequentially from the given Node (typically head node) through the next reference, one node after the other. I've added a toString() implementation to both, which will come handy later:
public class LinkedList {
protected Node head;
public LinkedList(Node head) {
super();
this.head = head;
}
static class Node {
protected int data;
protected Node next;
Node(int data, Node next) {
this.data = data;
this.next = next;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Node ");
builder.append(data);
if (null != next)
builder.append(" -> ");
return builder.toString();
}
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("LinkedList [");
Node node = head;
while (node != null) {
builder.append(node);
node = node.next;
}
builder.append("]");
return builder.toString();
}
}
Implementing a recursive delete method
Now, let's add a recursive delete() method. Deleting a node in a singly linked list can only be done by un-linking it from the previous node's next reference. The only exception to this rule is the head node, which we null to delete. Hence, it is obvious that we'll need (in addition to a starting point current node reference), a reference to the previous node.
Thus, our recursive delete() method signature can be:
private LinkedList delete(Node node, Node prev, int key)
Although the return type of this method can be omitted altogether (void) it is very useful to support chain-ability, so that API calls can become one-liner, dot separated syntax such as:
System.out.println(list.push(0).append(2).deleteAll(1));
Hence, for the sake of chain-ability, we'll return a reference to the entire LinkedList instance from this method too. As per the arguments list:
The first argument is the current node to check if it matches the given key. The next argument is the previous node, in case we need to un-link the current node. The last argument is the key we're looking for in all nodes to be deleted (unlinked).
The method modifier is private because it's not meant to be used publicly. We'll wrap it in a user friendly facade method, which will start the recursion with head as the current node and null as the previous node:
public LinkedList deleteAll(int key) {
return delete(head, null, key);
}
Now, let's see how we can implement the recursive delete(...) method and we begin with the two base conditions that will terminate the recursion; a null current node or a single node in the list, which is also the head node:
private LinkedList delete(Node node, Node prev, int key) {
if (node == null)
return this;
if (node == head && head.data == key && null == head.next) { // head node w/o next pointer
head = null;
return this;
}
//...more code here
}
Reaching the first base condition means either that we've reached the end of the linked list (found the key or not), or that the linked list is empty. We're done and we return a reference to the linked list.
The second base condition checks to see if our current node is the head node, and that it matches the key. In this case we also check if it happens to be the single node in the linked list. In such case the head node requires a 'special' treatment and must be assigned null in order to be deleted. Naturally, after deleting the head node, the list is empty and we're done, so we return a reference to the linked list.
The next condition checks if the current node matches the key, if it's the head node, but is not alone in the list.
private LinkedList delete(Node node, Node prev, int key) {
//...previous code here
if (node == head && head.data == key) { // head with next pointer
head = head.next;
return delete(head, null, key);
}
//...more code here
}
We'll later optimize this code but for now, in such a case we simply move the reference to head one step forward, so head is effectively deleted (the old reference will be garbage collected) and we recur with the new head as the current node and null is still the previous node.
The next case covers a regular (middle or tail) node matching the key:
private LinkedList delete(Node node, Node prev, int key) {
//...previous code here
if (node.data == key) {
prev.next = node.next;
return delete(prev, null, key);
}
//...more code here
}
In this case we delete the current node by un-linking the next pointer of the previous node from the current node and assigning it the next to the current node address. We essentially 'skip' the current node, which becomes grabage. We then recur with the previous node being the current node and null as the previous node.
In all of these handled cases we had a match for key. Finally, we handle the case where there's no match:
private LinkedList delete(Node node, Node prev, int key) {
//...previous code here
return delete(node.next, node, key);
}
Obviously, we recur with the next node as the current node, and the old current node as the previous node. The key remains the same through all recursion calls.
The entire (un-optimized) method now looks like this:
private LinkedList delete(Node node, Node prev, int key) {
if (node == null)
return this;
if (node.data == key && node == head && null == node.next) { // head node w/o next pointer
head = null;
return this;
}
if (node.data == key && node == head) { // head with next pointer
head = head.next;
return delete(head, null, key);
}
if (node.data == key) { // middle / tail
prev.next = node.next;
return delete(prev, null, key);
}
return delete(node.next, node, key);
}
Tail Recursion Optimization
Many compilers (javac included) can optimize recursive methods, if they use a tail-recursion. A recursive method is tail recursive when a recursive call is the last thing executed by the method. The compiler can then replace the recursion with a simple goto/label mechanism and save the extra memory space required in run-time for each recursion frame.
We can easily optimize our recursive delete(...) method to comply. Instead of returning recursively from each of the handled conditions (cases) we can keep a reference to the current node and previous node prev and assign them with appropriate values inside each case handling. This way, the only recursive call will happen at the end of the method:
private LinkedList delete(Node node, Node prev, int key) {
if (node == null)
return this;
if (node.data == key && head == node && null == node.next) { // head node w/o next pointer
head = null;
return this;
}
Node n = node.next, p = node;
if (node.data == key && head == node) { // head with next pointer
head = head.next;
n = head;
p = null;
} else if (node.data == key) { // middle / tail
prev.next = node.next;
n = prev;
p = null;
}
return delete(n, p, key);
}
To test this recursive method:
I've added a simple main test driver method to test the delete(...) method implementation, via the facade method deleteAll(...):
public static void main(String[] args) {
LinkedList list = new LinkedList(new Node(0, new Node(1, new Node(1, new Node(2, new Node(2, new Node(3, null)))))));
System.out.println(list);
System.out.println(list.deleteAll(6));
System.out.println(list.deleteAll(1));
System.out.println(list.deleteAll(3));
System.out.println(list.deleteAll(2));
System.out.println(list.deleteAll(0));
}
The output (using my supplied toString() methods) is:
LinkedList [Node 0 -> Node 1 -> Node 1 -> Node 2 -> Node 2 -> Node 3]
LinkedList [Node 0 -> Node 1 -> Node 1 -> Node 2 -> Node 2 -> Node 3]
LinkedList [Node 0 -> Node 2 -> Node 2 -> Node 3]
LinkedList [Node 0 -> Node 2 -> Node 2]
LinkedList [Node 0]
LinkedList []
Although it's been 3 years since the initial post, I trust some other beginning Java programmers, if not the OP, find this explanation useful.
after struggling i managed to solve the problem, here is the answer, but i am still not sure about the complexity whether it's O(n) or O(log n).
public void delete(int index){
//check if the index is valid
if((index<0)||(index>length())){
System.out.println("Array out of bound!");
return;
}
//pass the value head to temp only in the first run
if(this.index==0)
temp=head;
//if the given index is zero then move the head to next element and return
if(index==0){
head=head.next;
return;}
//if the array is empty or has only one element then move the head to null
if(head.next==null||head==null){
head=null;
return;}
if(temp!=null){
prev=temp;
temp=temp.next;
this.index=this.index+1;
//if the given index is reached
//then link the node prev to the node that comes after temp
//and unlink temp
if(this.index==index){
prev.next=temp.next;
temp=null;
return;
}
//if not then call the function again
delete(index);
}
}
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.
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.