Can someone explain why
temp.setNext(current.getNext()); has been used I am not understanding
public void add(Object data, int index)
// post: inserts the specified element at the specified position in this list.
{
Node temp = new Node(data);
Node current = head;
// crawl to the requested index or the last element in the list,
// whichever comes first
for(int i = 1; i < index && current.getNext() != null; i++)
{
current = current.getNext();
}
// set the new node's next-node reference to this node's next-node reference
temp.setNext(current.getNext());
// now set this node's next-node reference to the new node
current.setNext(temp);
listCount++;// increment the number of elements variable
}
You want the new Node (referenced by the temp variable) to be inserted before the node at the index position, which is referenced by current.getNext() after the while loop is done.
Therefore you first set the next Node of temp to current.getNext() (temp.setNext(current.getNext());) and then set the next Node of current to temp (current.setNext(temp);). This places temp between current and the original current.getNext().
before :
... -> current -> current.getNext() -> ...
after :
... -> current -> temp -> current.getNext() (the original current.getNext()) -> ...
Related
I was going through a sum on geeksforgeeks.com for adding two linked lists. And I am confused in the answer provided.
Node addTwoLists(Node first, Node second) {
Node res = null; // res is head node of the resultant list
Node prev = null;
Node temp = null;
int carry = 0, sum;
while (first != null || second != null) //while both lists exist
{
// Calculate value of next digit in resultant list.
// The next digit is sum of following things
// (i) Carry
// (ii) Next digit of first list (if there is a next digit)
// (ii) Next digit of second list (if there is a next digit)
sum = carry + (first != null ? first.data : 0)
+ (second != null ? second.data : 0);
// update carry for next calulation
carry = (sum >= 10) ? 1 : 0;
// update sum if it is greater than 10
sum = sum % 10;
// Create a new node with sum as data
temp = new Node(sum);
// if this is the first node then set it as head of
// the resultant list
if (res == null) {
res = temp;
} else // If this is not the first node then connect it to the rest.
{
prev.next = temp;
}
// Set prev for next insertion
prev = temp;
// Move first and second pointers to next nodes
if (first != null) {
first = first.next;
}
if (second != null) {
second = second.next;
}
}
if (carry > 0) {
temp.next = new Node(carry);
}
// return head of the resultant list
return res;
}
I understand that we have created three Nodes res, prev and temp and I don't understand how each one of them are getting updated simultaneously.
if (res == null) {
res = temp;
} else // If this is not the first node then connect it to the rest.
{
prev.next = temp;
}
Like here, how the 2nd element would be added in res when we are adding it in prev.next.
And below :
if (carry > 0) {
temp.next = new Node(carry);
}
If we are adding the last element in temp, how will it reflect in res?
The code seems to be working but I am having a hard time understanding this concept.
Please help. Thanks in advance.
res, prev and temp are references to a Node. When you write something like res = tmp; it means that now res and tmp refer to the same Node instance, and any changes made to this instance using, for example, res reference will remain when you use tmp reference.
here is the same code but with additional comments to try to help explain what is happening. This code appears to be taking two head nodes from link lists where each node contain a single digit, then adding the digits together to create a new list of single digits (e.g. 1->2->3 and 5->6->7->8 with = 1+5->2+6->3+7->0+8. Note that the third set results in a carry over so the final values in the returned list would be 6->8->0->9).
Thus, this code is not adding to two link lists together, it is adding the data contained
in each of the nodes of the two lists and putting the result into a third list.
My additional comments in the code are prefixed with WCK -
Node addTwoLists(Node first, Node second) {
Node res = null; // res is head node of the resultant list
Node prev = null;
Node temp = null;
int carry = 0, sum;
while (first != null || second != null) //while both lists exist WCK actually this is While at least one of the lists exists, I believe the comment is wrong and the code is right
{
// Calculate value of next digit in resultant list.
// The next digit is sum of following things
// (i) Carry
// (ii) Next digit of first list (if there is a next digit)
// (ii) Next digit of second list (if there is a next digit)
sum = carry + (first != null ? first.data : 0)
+ (second != null ? second.data : 0);
// update carry for next calulation
carry = (sum >= 10) ? 1 : 0; // WCK - assumes sum <20; is only carrying at most 1
// update sum if it is greater than 10
sum = sum % 10;
// Create a new node with sum as data
temp = new Node(sum);
// if this is the first node then set it as head of
// the resultant list
// WCK - the first time through the loop, res will be null
// WCK - each subsequent time through the loop, the else is invoked to link the new node to the one from the previous iteration thus linking them
if (res == null) {
res = temp; //WCK - as #ardenit says, both res and temp point to the same node at this point
} else // If this is not the first node then connect it to the rest.
{
prev.next = temp;
}
// Set prev for next insertion
// WCK - now they are starting to set up for the next iteration.
// WCK - the first time through, res, prev and temp all point to the same node after this statement is executed.
prev = temp;
// Move first and second pointers to next nodes
if (first != null) {
first = first.next;
}
if (second != null) {
second = second.next;
}
// WCK - the first time through the loop, both of the lists passed in
// have been advanced to the next node in their respective lists.
// res and prev will point to the temp. As the next iteration of the loop
// starts, temp will be pointed to a new node while res and prev will
// still point to the same node created in the first iteration. As the
// second iteration executes, prev is set to point to the new temp
// where you see (prev.next = temp) and then prev is advanced to the
// this new node as well. res will not be changed again (it is only set
// once in the first iteration)
}
// WCK - now that the loop is finished, there may be a final carry value
if (carry > 0) {
temp.next = new Node(carry);
}
// return head of the resultant list
return res;
}
Why each time we create new node p.next so we need to assign null to this.next? isn't always null any way? and which role does it play in LinkedList ?
if we try to print out this.next it will be null before we assign it to null.
System.out.println(this.next);
Result is null
Also if p.next point to the new node why we need to set p = p.next to point to the same node? if the purpose to set tail to p at last, can't we just set tail = p.next which is the last one after for loop is finished.
public class EnkeltLenketListe<T>{
private T value;
private Node<T> next;
private Node(T value, Node<T> next)
{
System.out.println(this.next);
this.next = next;
this.value = value;
}
}
private Node<T> head, tail;
public EnkeltLenketListe(T[] a)
{
this();
int i = 0; for (; i < a.length && a[i] == null; i++);
if (i < a.length)
{
head = new Node<>(a[i], null);
Node<T> p = head;
for (i++; i < a.length; i++)
{
if (a[i] != null)
{
p.next = new Node<>(a[i], null);
p = p.next;
}
}
tail = p;
}
}
Why each time we create new node p.next so we need to assign null to this.next?
while adding and removing a nodes, we have to make sure that nodes don't point to unintended nodes. they might have pointing to some nodes.
why we need to set p = p.next to point to the same node
to locate and maintain your position in the list while you are traversing the list, you start from head, and continue to remaining nodes. if p=p.next, how are going to traverse the list?
can't we just set tail = p.next which is the last one after for loop is finished.
No, we can not because in this case p.next is equivalent to p.p.next because p was set to p.next inside the loop. test it by adding the following before tail=p, you should get null
System.out.println(p.next);
Edited:
your list is singly linked list which means every node except the tail should have a pointer to next node, you started with
head = new Node<>(a[i], null);
Node<T> p = head;
in this case p and head are pointing Node 0 see image below. if the next NOde in the array is not null, let see what happens in the for loop
p.next = new Node<>(a[i], null);
p = p.next;
In this case p.next is pointing to Node 1 (see image below), where as p which were pointing to Node 0 is now set to point to Node 1. so both are pointing to 'Node 1`. the last one:
tail = p;
You said that why don't we just tail=p.next? No, we can not because in this case p.next is equivalent to p.p.next because p was set to p.next inside the loop.
read about singly linked list here
Try to use contradiction. If you didn't set p = p.next, in the next iteration of the loop, again you will set the new node to the next position of the previous node. Hence, all the time p is the head and you didn't move the p anymore!
Therefore, you need to move p in each iteration after setting p.next. Indeed, it is a pointer to the last element of the list.
I'm struggling with my solution for a question on InterviewBit.
I linked to the full description, but in short:
1) You are given the head node of a linkedlist
2) take the first half of the list and change the values so that:
"1st node’s new value = the last node’s value - first node’s current value
2nd node’s new value = the second last node’s value - 2nd node’s current value"
Here is my approach (it compiles but does not mutate the list at all)
I see that my method does not actually modify the original list -- it seems like what I'm doing is making a new list with the correctly altered values, but not changing the original.
/**
* Definition for singly-linked list.
* class ListNode {
* public int val;
* public ListNode next;
* ListNode(int x) { val = x; next = null; }
* }
*/
public class Solution {
public ListNode subtract(ListNode a) {
ListNode current = a;
int length = 0;
//get length
while(current.next != null){
length++;
current = current.next;
}
length += 1;
while(current.next != null){
double half = Math.floor(length/2);
for(int i=0; i<half; i++ ){
//
// if(i == 0){
// int aval = (nthToLast(a, length)).val - a.val;
// a.val = ((nthToLast(a, length-i)).val - a.val);
// a.next = current;
// }
current.val = ((nthToLast(a, length-i)).val - current.val);
current = current.next;
}
}
return a;
}
/* Helper function that given LinkedList head, and int n,
returns the nth to last ListNode in the LinkedList */
public ListNode nthToLast(ListNode head, int n){
ListNode nth = head;
ListNode ahead = head;
/* strategy: set nth to head, and 'ahead' to n places in front of 'nth'
increment at same speed and then when 'ahead' reaches the end, 'nth'
will be in the nth place from the end.
*/
while(ahead.next != null){
for(int i=0; i<n; i++){
ahead = ahead.next;
}
nth = nth.next;
ahead = ahead.next;
}
return nth;
}
}
Also -- I'm trying to get better at questions like these. Is this an ok approach for this question? I'd like to figure out how to make this work, but also if this is an all around bad approach please let me know.
break code into simple helper functions,
make a function to get value of nth element in the linked list(this function is very easy to write)
,and then traverse the list upto the half every time calling that function to get the value of listSize-i member of the list and edit the value of the the ith member of the list. and make changes to the 1st few elements manually to check weather your linkList implementation is working or not
/**
* Definition for singly-linked list.
**/
class ListNode {
public int val;
public ListNode next;
ListNode(int x) { val = x; next = null; }
}
public class Solution {
public ListNode subtract(ListNode a) {
ListNode current = a;
int length = 0;
//get length
while(current.next != null){
length++;
current = current.next;
}
length += 1;
int half = length/2;
//logic of this loop is
//go from 0 to half of the list
// j goes from the last element to half
//for example if size of list is 6 (indexing from 0)
//when i is 0 j is 5
//when i is 1 j is 4 and so on
//so you get what you wanted
for(int i=0,j=length-1; i<half; i++,j-- ){
current.val=nthElement(a,j).val-current.val;
current = current.next;
}
return a;
}
/* Helper function that given LinkedList head, and int n,
returns the nth node of LinkedList */
public ListNode nthElement(ListNode head, int n){ //e.g-if n is 5 it will return the 5th node
ListNode nth = head;
for(int i=0; i<n; i++){
nth = nth.next;
}
return nth;
}
}
Completed my hw and I got it wrong. I do not understand why.
For my insert front I do the following.
head.next.prev = newNode;
newNode.next = head;
newNode.prev = null;
head.prev = newnode;
head.next.prev = head;
size++;
But instead the solution looks like this following
head.next.prev = newNode(item, head, head.next); // newNode(item,prev,next); So basically head.next.prev is pointing to a newnode here newnode.prev = head and newnode.next = head.next. Ok that make sense.
head.next = head.next.prev; // huh?
size++;
to me the solution doesn't make sense and my solution is perfectly logical. If you make head.next.prev = a new node, you should make head.next.prev = head, or else there will be a jump right? Also head.next = head.next.prev; doesn't make any sense. That line is basically saying head.prev is pointing to the head itself. Shouldn't it be head.next.prev = head;?
Can anyone point out what's going on? i know the format between the solutions is different but i'm more interested in the logic
The complete code is shown below
There's a lot of confusion. So here's how head is declared
public class DList {
/**
* head references the sentinel node.
* size is the number of items in the list. (The sentinel node does not
* store an item.)
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
protected DListNode head;
protected int size;
/* DList invariants:
* 1) head != null.
* 2) For any DListNode x in a DList, x.next != null.
* 3) For any DListNode x in a DList, x.prev != null.
* 4) For any DListNode x in a DList, if x.next == y, then y.prev == x.
* 5) For any DListNode x in a DList, if x.prev == y, then y.next == x.
* 6) size is the number of DListNodes, NOT COUNTING the sentinel,
* that can be accessed from the sentinel (head) by a sequence of
* "next" references.
*/
/**
* newNode() calls the DListNode constructor. Use this class to allocate
* new DListNodes rather than calling the DListNode constructor directly.
* That way, only this method needs to be overridden if a subclass of DList
* wants to use a different kind of node.
* #param item the item to store in the node.
* #param prev the node previous to this node.
* #param next the node following this node.
*/
protected DListNode newNode(Object item, DListNode prev, DListNode next) {
return new DListNode(item, prev, next);
}
/**
* DList() constructor for an empty DList.
*/
public DList() {
head = newNode(null, head, head);
head.next = head;
head.prev = head;
size = 0;
}
public insertfront(Object item){
???????????}
//////////////////// below is the DlistNoe.java
public class DListNode {
/**
* item references the item stored in the current node.
* prev references the previous node in the DList.
* next references the next node in the DList.
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
public Object item;
protected DListNode prev;
protected DListNode next;
/**
* DListNode() constructor.
* #param i the item to store in the node.
* #param p the node previous to this node.
* #param n the node following this node.
*/
DListNode(Object i, DListNode p, DListNode n) {
item = i;
prev = p;
next = n;
}
}
There's a lot wrong with your insertion code. Just read it in English:
head.next.prev = newNode;
Point the first node's "prev" to the new node (ok)
newNode.next = head;
Point the new node's "next" to the head (what?)
newNode.prev = null;
Point the new node's "prev" to null (it's the first node, so it should point to head)
head.prev = newnode;
Point the head's "prev" to null (you're inserting at the front so you shouldn't be touching this)
head.next.prev = head;
Point the first node's prev to head (undoing what you did in the first step)
So now you have a head that's still pointing to the old first element, and is not pointing back to the last element of the list anymore. And a new element that is not fully inserted (its "prev" is not pointing at anything, and its "next" is pointing at the wrong element).
Yeah, not really correct, I'd say. If you read the correct solution like the above, hopefully you'll see it makes more sense.
The trouble with structures like linked lists is that when you start modifying references, you lose which nodes are which.
So, let's name some nodes.
The linked list before insertion:
H -> A -> B -> C
H.next = A
H.prev = null
A.next = B
A.prev = H
And so on...
The Goal linked list:
H -> N -> A -> B -> C
H.next = N
H.prev = null (unchanged)
A.next = B (unchanged)
A.prev = N
N.next = A
N.prev = H
Based on the DList invariants and the given solution, there is a head node that does not hold a value that stays the head.
Then let's step through your code:
head.next.prev = newNode; // H.next -> A, A.prev = N. This seems fine.
newNode.next = head; // N.next = H. What? This doesn't match our goal.
newNode.prev = null; // N.prev = null. Also doesn't match our goal.
head.prev = newnode; // H.prev = n. Also doesn't match our goal.
head.next.prev = head; // H.next -> A, looks like you mean this to be N, but its still A.
// thus A.prev = H. Also doesn't match our goal.
size++;
Finally, let's look at the given solution.
head.next.prev = newNode(item, head, head.next);
// First the function, H.next -> A, so...
// N.prev = H. Matches goal.
// N.next = A. Also matches goal.
// Then the assignment:
// head.next -> A, A.prev = N. Matches goal.
head.next = head.next.prev;
// head.next -> A, A.prev -> N, H.next = N. Matches goal.
size++;
And thus, all 4 changed references have been set.
Consider:
Node reverse(Node head) {
Node previous = null;
Node current = head;
Node forward;
while (current != null) {
forward = current.next;
current.next = previous;
previous = current;
current = forward;
}
return previous;
}
How exactly is it reversing the list?
I get that it first sets the second node to forward. Then it says current.next is equal to a null node previous. Then it says previous is now current. Lastly current becomes forward?
I can't seem to grasp this and how it's reversing. Can someone please explain how this works?
You reverse the list iteratively and always have the list in the interval [head, previous] correctly reversed (so current is the first node that has its link not set correctly). On each step you do the following:
You remember the next node of current so that you can continue from it
You set the link of current to be pointing to previous, which is the correct direction if you think about it
You change previous to be current, because now current also has its link set correctly
You change the first node that does not have its link set correctly to be the one remembered in the first step
If you do that for all the nodes, you can prove (with induction for instance) that the list will be correctly reversed.
The code simply walks the list and inverts the links until it reaches the previous tail, which it returns as the new head.
Before:
Node 1 (Head) -> Node 2 -> Node 3 -> Node 4 (Tail) -> null
After:
null <- Node 1 (Tail) <- Node 2 <- Node 3 <- Node 4 (Head)
The easiest way to think about it is to think like this:
First add the head of the list to a new linked list.
Keep iterating through the original and keep adding the nodes before the head of the new linked list.
Diagram:
Initially:
Original List -> 1 2 3 4 5
New List -> null
1st Iteration
Original List -> 1 2 3 4 5
New List -> 1->null [head shifted to left, now newHead contains 1 and points to null]
2nd Iteration
Original List -> 1 2 3 4 5
New List -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]
3rd Iteration
Original List -> 1 2 3 4 5
New List ->3 -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]
Now it keeps looping through till the end. So finally the new list becomes:
New List-> 5 -> 4 -> 3 -> 2 -> 1 -> null
The code for the same should be like this (made it easy to understand):
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public ListNode reverseList(ListNode head) {
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
ListNode current = head;
ListNode previous = new ListNode(head.val);
previous.next = null;
while(current.next != null) {
current = current.next;
previous = addBeforeHead(current, previous);
}
return previous;
}
private ListNode addBeforeHead(ListNode node, ListNode head) {
if (node == null) return null;
ListNode temp = new ListNode(node.val);
temp.next = head;
head = temp;
return head;
}
public Node getLastNode()
{
if(next != null)
return next.getLastNode();
else
return this;
}
public Node reverse(Node source)
{
Node reversed = source.getLastNode();
Node cursor = source;
while(cursor != reversed)
{
reversed.addNodeAfter(cursor.getInfo());
cursor = cursor.getNodeAfter();
}
source = reversed;
return source;
}
I call it "cherry picking". The idea is to minimize the number of swaps. Swapping happens between a near and far index. It's a twp-pass algorithm.
(Odd length) A -> B -> C -> D -> E
(Even length) A -> B -> C -> D
Pre-Condition: N >= 2
Pass 1: Count N, the number of elements
Pass 2:
for(j=0 -> j<= (N/2 -1))
{
swap(j, (N-1)-j)
}
Example 1:
For above Odd length list, N = 5 and there will be two swaps
when j=0, swap(0, 4) // Post swap state: E B C D A
when j=1, swap(1, 3) // Post swap state: E D C B A
The mid point for odd length lists remains intact.
Example 2:
For above Even length list, N = 4 and there will be two swaps
when j=0, swap(0, 3) // Post swap state: D B C A
when j=1, swap(1, 2) // Post swap state: D C B A
Swapping applies to data only, not to pointers, and there might be any sanity checks missed, but you got the idea.
list_t *reverse(list_t *a)
{
list_t *progress = NULL;
while(a)
{
list_t *b; //b is only a temporary variable (don't bother focusing on it)
b = a->next;
a->next = progress; // Because a->next is assigned to another value,
// we must first save a->next to a different
// variable (to be able to use it later)
progress = a; // progress is initially NULL (so a->next = NULL
// (because it is the new last element in the list))
a = b; // We set a to b (the value we saved earlier, what
// a->next was before it became NULL)
/*
Now, at the next iteration, progress will equal a, and a will equal b.
So, when I assign a->next = progress, I really say, b->next = a.
and so what we get is: b->a->NULL.
Maybe that gives you an idea of the picture?
What is important here is:
progress = a
and
a = b
Because that determines what a->next will equal:
c->b->a->0
a's next is set to 0
b's next is set to a
c's next is set to b
*/
}
return progress;
}
The basic idea is to detach the head node from the first list and attach it to the head of a second list. Keep repeating until the first list is empty.
Pseudocode:
function reverseList(List X) RETURNS List
Y = null
WHILE X <> null
t = X.next
X.next = Y
Y = X
X = t
ENDWHILE
RETURN Y
ENDfunction
If you wish to leave the original list undisturbed then you can code a copying version recursively with the use of a helper function.
function reverseList(List X) RETURNS List
RETURN reverseListAux(X, null)
ENDfunction
function reverseListAux(List X, List Y) RETURNS List
IF X = null THEN
RETURN Y
ELSE
RETURN reverseListAux(X.next, makeNode(X.data, Y))
ENDfunction
Note that the helper function is tail recursive. This means that you can create a copying reversal using iteration.
function reverseList(List X) RETURNS List
Y = null
WHILE X <> null
Y = makeNode(x.data, Y)
X = X.next
ENDWHILE
RETURN Y
ENDfunction
Reversing a singly-linked list using iteration:
current = head // Point the current pointer to the head of the linked list
while(current != NULL)
{
forward = current->link; // Point to the next node
fforward = forward->link; // Point the next node to next node
fforward->link = forward; // 1->2->3,,,,,,,,,this will point node 3 to node 2
forward->link = current; // This will point node 2 to node 1
if(current == head)
current->link = NULL; // If the current pointer is the head pointer it should point to NULL while reversing
current = current->link; // Traversing the list
}
head = current; // Make the current pointer the head pointer
Implementation of a singly-linked list reversal function:
struct Node
{
int data;
struct Node* link;
}
Node* head = NULL;
void reverseList()
{
Node* previous, *current, *next;
previous = NULL;
current = head;
while(current != NULL)
{
next = current-> link;
current->link = previous;
previous = current;
current = next;
}
head = previous;
}
Here is a simple function to reverse a singly linked list
// Defining Node structure
public class Node {
int value;
Node next;
public Node(int val) {
this.value=val;
}
}
public LinkedList reverse(LinkedList list) {
if(list==null) {
return list;
}
Node current=list.head;
Node previous=null;
Node next;
while(current!=null) {
next=current.next;
current.next=previous;
previous=current;
current=next;
}
list.head=previous;
return list;
}
For better understanding, you can watch this video https://youtu.be/6SYVz-pnVwg
If you want to use recursion:
class Solution {
ListNode root=null;
ListNode helper(ListNode head)
{
if (head.next==null)
{ root= head;
return head;}
helper (head.next).next=head;
head.next=null;
return head;
}
public ListNode reverseList(ListNode head) {
if (head==null)
{
return head;
}
helper(head);
return root;
}
}
public void reverseOrder() {
if(head == null) {
System.out.println("list is empty");
}
else {
Node cn = head;
int count = 0;
while (cn != null) {
count++;
cn = cn.next;
}
Node temp;
for(int i = 1; i<=count; i++) {
temp = head;
for(int j = i; j<count; j++) {
temp = temp.next;
}
System.out.print(temp.data+" ->");
}
System.out.print("null");
}
}