Place top of stack at end of linked chain instead of beginning - java

I am working on a problem: create a stack using a linked chain that places the new entry (top of stack) at the end of the chain, not the beginning. Part of the solution involves maintaining a reference to the first and last nodes and the next to last node. Also, I cannot traverse the chain. I cannot think of a solution because I cannot think of a way to update the reference to the next to last node when the top entry is popped off the stack?
(This is a textbook question. The beginning of the chain contains a reference to the next node. The end of the chain's reference to the next node is null)

Beginning and end are abstract terms. Just initialize a node to contain the first element. Something like the following:
Node tail = null;
..
..
Then to add a new node.
public void push(T val) {
Node = new Node(val);
Node.next = tail;
tail = node;
}
You're adding it at the tail and then the new node becomes the tail. Then when you iterate thru it you simply start at the tail and move towards the head using the next reference.
To pop the stack.
public T pop() {
if (tail != null) {
object = tail.object;
tail = tail.next;
}
return null;
}
You will need to create a generic class Node. And you may want to have an isEmpty() method.

Related

Program took more time than expected error

Below is a program to reverse a doubly linked list in gfg.
When I try to submit, I get the following error
Your program took more time than expected. Time Limit Exceeded
Expected Time Limit 0.00sec.
Can anyone tell me how to decrease my program's time?
Code
public static Node reverseDLL(Node head)
{
Node p,cur;
p=head;
cur=head.next;
while(cur!=null)
{
if(cur.next==null)
{
p.next=cur.next;
cur.next=head;
head.prev=cur;
head=cur;
break;
}
p.next=cur.next;
cur.next.prev=p;
cur.next=head;
head.prev=cur;
head=cur;
cur=p.next;
}
return head;
}
Your code is not correct:
The prev member of the (original) tail node is not set correctly. It is not set in the if block, but in the previous iteration, where it got its value with cur.next.prev=p, which is setting it to the (original) head node. This creates an infinite loop in the data structure. In the end, none of the prev links is null. It might be that the testing framework keeps following those prev links in circles until a time out happens.
Also, the function assumes that head is not null. This may not be guaranteed.
There are also too many assignments happening. With a doubly linked list it is quite simple: just swap the value of next and prev in every node:
public static Node reverseDLL(Node head)
{
if (head == null) {
return null;
}
Node next = head.next;
while (next != null) {
head.next = head.prev;
head.prev = next;
head = next;
next = head.next;
}
head.next = head.prev;
head.prev = null;
return head;
}
this is classic solution for O(N) time, so I guess time constraint for this task is required to. solve it for O(1).
Take a look for this thread: https://www.google.com/url?sa=t&source=web&rct=j&url=https://discuss.codechef.com/t/reverse-a-doubly-linked-list-in-o-1/72850&ved=2ahUKEwjipdrQw_T1AhVYLTQIHahIDx8QFnoECBQQAQ&usg=AOvVaw1c0BDUotM0suEK7I4B9pQs

"object = this" in java

I'm familiar with the 'this' keyword used in java, it is used to reference the current object. The following piece of code shows how a node of a LinkedList is created:
class Node {
Node next = null;
int data;
public Node(int d) {
data = d;
}
void appendToTail(int d) {
Node end = new Node(d);
Node n = this;
while (n.next != null) {
n = n.next;
}
n.next = end;
}
}
But here I'm not sure what the following line in the above code states:
Node n = this;
I'm pretty sure that 'this' here is referenced to the current object, but is this object head, tail or any other node in the LinkedList? Not sure if my question makes perfect sense, but any help is greatly appreciated.
I assume the appendToTail(int d) method appends the newly created node to the end of the list regardless of which Node its called from.
What happens is that one must find the end of the list in order to append the new Node to the end of it. Since we know that the node it is called from is in the list, it's an ideal starting point. Hence we choose the starting point as "this" node. But, this node is not necessarily the end of the list (in fact, it can be anywhere in the list), so we store it in a temporary variable Node n = this and continue changing our temporary variable until its the last node in the list, to which the new node can be added.
It's equivalent to starting from a random point (this) in a list and moving from that point to the end, wherever that is.
Hope this answered your question.
I'm pretty sure that 'this' here is referenced to the current object
Yup.
but is this object head, tail or any other node in the LinkedList?
That depends where the method was called from or if the list contains this Node at all.
All the method does is assign a temporary reference to the current Node so it can be iterated over. You can't say which Node it is without more information.
From comments - If you call appendToTail() on the head, this will be the head. If you call it on the tail, this will be the tail. If you call it on a middle node, this will be that middle node.

Deleting a node in the middle of a single linkedlist

I have written a program that removes a node in the single linkedlist given the node.
public class Solution {
/**
* #param node: the node in the list should be deleted
* #return: nothing
*/
public void deleteNode(ListNode node) {
// write your code here
// if node.next==null, we cannot delete the current node without given the previous node
if(node == null || node.next == null) return;
ListNode next = node.next;
node.val = next.val;
node.next = next.next;
// I wonder if this link needs to be removed as well
next.next = null;
}
}
The problem is pretty simple. However, many code samples online do not contain this line I wrote:
next.next = null;
Without this line, we already remove the node. After that, although nothing is pointing to "next", "next" still points to next.next. Without setting next.next = null, will the Java garbage collector remove this deleted node?
Indeed it will. The gc iterates over all objects and checks wether someone else points to it. If not, it is marked for deletion.

Java Queue Implementation with Pointers

I need help understanding this. I know how to implement the queue but there is one small part bothering me. I drew on my notebook the flow of how things work but I don't get how the head has a nextNode without me setting it. How does the head end up pointing to the next node?
public void enqueue(T data){
count++;
Node<T> current = tail;
tail = new Node<>(data);
if(isEmpty()) {
///////////////////////////////////////////////////////////////////////////////
// when this runs, doesn't head.getNextNode point to null?
// if the list is empty, then tail is null.
// On the deque method, I can sout head.getNextNode() and I get data back, how?
///////////////////////////////////////////////////////////////////////////////
head = tail;
} else {
current.setNextNode(tail);
}
}
Below, the dequeing works fine, I think I'm having an issue understanding the whole reference/pointer thing
public T dequeue() {
if(isEmpty()) {
return null;
}
count--;
T dataToRemove = head.getData();
/////////////////////-+{[UPDATE]}+-////////////////////////////////
// WHERE DOES HEAD GET THE NEXT NODE FROM? THIS WORKS, BUT WHERE IS
// THE NEXT NODE COMING FROM IS WHAT I'M ASKING?
///////////////////////////////////////////////////////////////////
head = head.getNextNode();
return dataToRemove;
}
I figured it out:
When the list is empty, the head points to tail
then, when the enqueue method gets called again,
current will be pointing to tail, but head will still be pointing to tail reference
so now head is pointing to the same reference as current
in the else statement, current sets next node to the same reference the
head is pointing to. That's how the head gets its nextNode set.
When the method runs again, current will
point to another reference again but head will still be pointing to its original reference. BAM
public void enqueue(T data){
count++;
Node<T> current = tail;
tail = new Node<>(data);
if(isEmpty()) {
head = tail;
} else {
current.setNextNode(tail);
}
}

Circular Linked List Node Insertion Java

I tried implementing the insert method for circular linked list. I think I had some success.
Problem:
When I display the list. The display method will loop because every next variable of the link is linked to a non-null node object. So head will never be a null object. From what I recall about singly linked list, head always point to the first node in the list or the first node with data inside of it.
My conceptual understanding of circular linked list:
From what I can understand circular linked is somewhat like a singly linked list but with a slight twist: the next variable of the tail object points to the head.
I'm coding it like the diagram has presented provided by the source link.
Source: http://sourcecodemania.com/circular-linked-lists/
public void insert(String data)
{
Link link = new Link(data);
if(head == null)
{
head = link;
tail= link;
}
else
{
tail.next = link;
tail = link;
tail.next = head;
}
}
public void display()
{
// good implementation for display #2
while(head != null)
{
// System.out.println (head.data);
head = head.next;
}
}
Once you insert at least one element, you would never come across null. It will keep on going till infinity.
Also, it might not be a good idea to modify head just for displaying the list. Operation like display should not have any side effects.
In stead, keep a member field size in your list class and update it in each insert and delete method.
Now you would know how many times you should iterate the loop.
ListClassName current = head; // Head is not modified.
for (int i = 0; i < this.size; i++) {
// System.out.println (current.data);
current = current.next;
}
Good luck.
You can keep a reference to the first Link object and check to make sure head is not equal to this object while looping:
public void display()
{
boolean first=true;
Link firstItem=null;
// good implementation for display #2
while(head != null && head!= firstItem)
{
if(first){
firstItem=head;
first=false;
}
// System.out.println (head.data);
head = head.next;
}
}

Categories

Resources