Singly Linked List - Put last node after first node - java

Let's say that I've a list that goes by 1->2->3->4->5. I want to put the last node after the first one so it goes like 1->5->2->3->4. This is my code but it doesn't work
public void Manipulate(){
Node curr = head;
Node next = null;
Node last = head;
while(last.next != null){
last = last.next;
}
next = curr.next;
last.next = next;
curr.next = next.next;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
SinglyLinkedList lista = new SinglyLinkedList();
int a = sc.nextInt();
int b = sc.nextInt();
lista.addFirst(a);
lista.insertAfter(a, b);
for(int i = 0; i < 2; i ++){
int c = b;
b = sc.nextInt();
lista.insertAfter(c, b);
}
lista.addLast(34);
lista.addLast(55);
lista.addLast("Ginger");
lista.Manipulate();
System.out.println(lista);
}

You already got some improvement suggestions, so here's a little explaination what you actually did wrong.
The result of your code (as is) would be:
1->3->4->5->2->3->4->5->2->3->4->5->2->3->4->5->2->3->4->5->2->3->4->5->2->3->4->5->2->3->->4->5->2->3->4->5->2->3->->4->5->2->3->4->5->2->3->4->5->2->3->4->5->2->3->->4->5->2->3->4->5->2->3->4->5->2->3->4->5->2->3->4->5->2->3->4->5->2->3->... (going on forever)
Which is why you run out of memory when trying to print that infinite beast.
First mistake: You need to actually make sure the element that will be the new last element does no longer have your former last element as next.
Second mistake: Your head element should have the former last element as next, not the next elements of its former next element.

// Edge case: list has zero or 1 node:
if(head == null || head.next == null) {
return;
}
Node prev = null;
Node last = head;
while(last.next != null){
prev = last;
last = last.next;
}
Node tmp = head.next;
head.next = last;
last.next = tmp;
// Prevent loop by setting the next of the new last to null
prev.next = null;

public void Manipulate() {
Node penultimate = null;
Node last = head;
while(last.next != null){
penultimate = last;
last = last.next;
}
if (penultimate != null){ // closes the list
penultimate.next = null;
}
if (last != head) { // move last element to second place
last.next = head.next;
head.next = last;
}
}

Related

Reverse subparts of a contiguous linked list in Java

I am trying to reverse a subpart of a singly-linked list where the subpart is a contiguous set of even elements, bordered by either the end of the list or an odd element.
So far, I know how to reverse a linked list but I'm unable to figure out how to check if the element is odd or if it's at the end.
Node reverse(Node head) {
// Write your code here
if(head == null) return null;
Node prev = null;
Node curr = head;
Node next = null;
while(curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
Example
Input:
list = [1, 2, 8, 9, 12, 16]
Output:
[1, 8, 2, 9, 16, 12]
The subparts in this example are 2,8 and 12,16
Node reverse(Node head) {
if(head == null) return null;
Node curr = head;
Node next = null;
Node prev = null;
while(curr!=null && curr.data%2==0) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
if(curr!=head) {
head.next = curr;
curr = reverse(curr);
return prev;
} else {
head.next = reverse(head.next);
return head;
}
}
Q. Given a singly linked list of integers, reverse every contiguous set of nodes that have only even values.
I/P = 1 2 3 3 4 6 8 5, O/P = 1 2 3 3 8 6 4 5, explanation -
There are two sub lists of even elements, which [2] and [4->6->8]. The sub list [4->6->8] has been reversed and the single sub list [2] need not be reversed.
Test Cases passed
1 3 8 3 4 2 6 5 single/multi even element in list,
2 4 6 1 3 even occurs at head,
1 4 4 6 8 even occurs till tail,
2 4 6 8 2 all even in the list
import java.util.*;
//import ds.List.ListNode; import your ListNode class
/*
public class ListNode {
public int val;
public ListNode next;
public ListNode(int x) { val = x; next = null; }
}
*/
class Solution{
public ListNode reverseEvenElements(ListNode head)
{
ListNode p = null;//prev
ListNode c = head;//curr
while(c != null){
if(c.val % 2 == 0){
ListNode start = p;
while(c != null && c.val % 2 == 0){
p = c;
c = c.next;
}
//end of even elements = p
//making end of even node to null so that reverse should stop
//otherwise it will reverse whole list
p.next = null;
ListNode[] node;// [head,tail]
// if start is null i.e. even element found at head itself
if(start == null){
node = reverseList(head);
head = node[0];//node[0] = head of reversed list
}else{// start != null
node = reverseList(start.next);
start.next = node[0];
}
node[1].next = c;//node[1] = tail of reversed list
}
if(c != null){
p = c;
c = c.next;
}
}
return head;
}
// this method will be called when even elements occurs till last even element we get
//in the original list returns head & tail of reversed list
public static ListNode[] reverseList(ListNode head){
ListNode p = null;
ListNode c = head;
ListNode n = head.next;
while(true){
c.next = p;
p = c;
c = n;
if(n == null)
break;
else
n = n.next;
}
return new ListNode[] {p, head};// [head,tail]
}
}
from what you given me i understood like :
input : [1,2,4,8,5,7,7,6,6,2,8,1,1,1,2,4]
output: [1,8,4,2,5,7,7,8,2,6,6,1,1,1,4,2]
i have edited your code for reverse to reverse till which will reverse intervals & created reverse_whole which will find those intervals
public ListNode reverse_whole(ListNode head) {
ListNode temp=head;
ListNode pre_temp=new ListNode(0,temp);
ListNode ans_pre = pre_temp;
while(temp!=null){
if(temp.val%2==0){
ListNode temp_till=temp;
while(temp_till!=null&& temp_till.val%2==0){
temp_till=temp_till.next;
}
// temp_till will iterate over even number interval after one
//so: 1,2,4,6,7 : 7 is temp_till
// reverse 2,4,6 so it become : 1,6,4,2,7
pre_temp.next=reverse_subpart(temp,temp_till);
temp=temp_till;
}
pre_temp=temp;
if(temp!=null)temp=temp.next;
}
return ans_pre.next;
}
public ListNode reverse_subpart(ListNode head,ListNode end) {
// Write your code here
if(head == null) return null;
ListNode prev = null;
ListNode curr = head;
ListNode next = null;
while(curr != end) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
head.next=end;
return prev;
}
run reverse_whole
if you have any doubt can write me
class LinkedList {
Node head;
Node curr = head;
Node next = null;
Node prev = null;
class Node {
int data;
Node next;
Node(int d)
{
data = d;
next = null;
}
}
void pairWiseSwap()
{
Node temp = head;
while (temp != null && temp.next!=null) {
int k = temp.data;
int j = temp.next.data;
if(k%2==0 && j%2==0) {
temp.data=j;
temp.next.data=k;
temp=temp.next.next;
continue;
}
temp = temp.next;
}
}
public void push(int new_data)
{
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
void printList()
{
Node temp = head;
while (temp != null) {
System.out.print(temp.data + " ");
temp = temp.next;
}
System.out.println();
}
public static void main(String args[])
{
LinkedList llist = new LinkedList();
llist.push(16);
llist.push(12);
llist.push(9);
llist.push(8);
llist.push(2);
llist.push(1);
System.out.println("Linked List before calling pairWiseSwap() ");
llist.printList();
llist.pairWiseSwap();
System.out.println("Linked List after calling pairWiseSwap() ");
llist.printList();
}
}

how to reduce doubly linked list complexity in the code

// Complete the sortedInsert function below.
/*
* For your reference:
*
* DoublyLinkedListNode {
* int data;
* DoublyLinkedListNode next;
* DoublyLinkedListNode prev;
* }
*
*/
static DoublyLinkedListNode sortedInsert(DoublyLinkedListNode head, int data) {
DoublyLinkedListNode Leader=head;
DoublyLinkedListNode newNode = new DoublyLinkedListNode(data);
while(Leader.next!=null){
if(data>Leader.data){
Leader = Leader.next;
}
else {
if(Leader.prev == null) {
newNode.next = Leader;
Leader.prev = newNode;
head = newNode;
return head;
}
}
}
if(Leader.next == null) {
if(data<Leader.data) {
newNode.prev = Leader.prev;
newNode.next = Leader;
Leader.prev.next = newNode;
return head;
} else {
newNode.prev = Leader;
Leader.next = newNode;
return head;
}
}
return head;
}
in the above-sorted insert method how to decrease this doubly linked list complexity, this is a hackerrank question I'm getting timed outs for the test cases I need help in decreasing the time complexity for this code.
You code will never come out of while loop.
Lets take the example. List = [(1), (4), (4)](only 1 element). New node is (4). Your result should be [(1), (4), (4), (4)]. But lets walk your code and check what will happen. Initially Leader = (1)
while(Leader.next!=null){ // 1
if(data>Leader.data){ // 3
Leader = Leader.next;
}
else { // 6
if(Leader.prev == null) { // 7
newNode.next = Leader;
Leader.prev = newNode;
head = newNode;
return head;
}
}
}
At line 1 check will pass (as (1).next is not null; in fact it is (4)).
At line 3 ((4) > (1)). Check pass. Leader = (1).next = (4). Jump to line 1
At line 1 check will pass (as (4).next is not null; in fact it is (4)).
At line 3 ((4) > (4)). Check Fail. Enter line 7
At line 7 check will fail ((4).prev is not null; in fact it is (4) - 1st 4). No update in Leader will take place. Leader will remain same & you will enter infinte loop from here.
You will have to take care of this. Maybe the Problem's discussion page will help. But do give it a through try.
My own try is included below:
static DoublyLinkedListNode sortedInsert(DoublyLinkedListNode head, int data) {
DoublyLinkedListNode n = new DoublyLinkedListNode();
n.data = data;
DoublyLinkedListNode curr = head;
if (head == null) {
return n;
}
// if given node is smaller than 1st node
if (data < curr.data) {
n.next = curr;
return n;
}
// find first node greater than given node
while (curr.next != null && curr.data < data) {
curr = curr.next;
}
// reached to the end.
if (curr.next == null && data >= curr.data) {
curr.next = n;
} else { // found the 1st node which is greater than given node
curr.prev.next = n;
n.next = curr;
}
return head;
}

Issues with reversing the linkedlist

I'm trying to learn about linked list and it has been little challenging for me. I'm trying to reverse the link list with recursive method. Here is my code:
public class ListNode {
Node head = null;
int nodeCount= 0;
int counter = 0;
ListNode(){
head = null;
}
public void insertNode( String name ) {
if (head == null) {
head = new Node(name, null);
nodeCount++;
} else {
Node temp = new Node(name, null);
temp.next = head;
head = temp;
nodeCount++;
}
}
public Node reverseTest(Node L){
// Node current = new Node(null,null);
if(L == null || L.next ==null){
return L;
}
Node remainingNode = reverseTest(L.next);
Node cur = remainingNode;
while(cur.next !=null){
cur=cur.next;
}
L.next = null;
cur.next = L;
return remainingNode;
}
public static void main(String[] args){
ListNode newList = new ListNode();
newList.insertNode("First");
newList.insertNode("Second");
newList.insertNode("Third");
newList.insertNode("Fourth");
newList.reverseTest(newList.head);
}
}
The problem I'm having with is the reverse method. When the method is over it only returns the last node with the value "First".Through the entire recursion remainingNode only holds and returs value from the base case which is confusing me. I was excepting it to move further through the nodes. After the method is executed newList holds only one node with next node as null and that node is the head now. I was assuming it will reverse the linkedlist with the sequence First --> Second--> Third --> Fourth. What am I doing wrong?
Actually, everything works here. Your only problem is in your main method: you don't get the result of your method.
newList.reverseTest(newList.head);
You need to actually set the new head with the result:
newList.head = newList.reverseTest(newList.head);
This would have been easier to see if you had declared your method static:
newList.head = ListNode.reverseTest(newList.head);
As a bonus, here is a fully recursive equivalent:
public static Node reverse(Node head) {
if (head == null || head.next == null) {
return head;
}
Node newHead = reverse(head.next);
// head.next points to the new tail, we push the former head at the end
head.next.next = head;
// now head has become the new tail, we cut the end of the list
head.next = null;
return newHead;
}

Practicing Singly Linked List implementation, stumped by my list reversal method throwing NullPointerException

Here is my singly linked list code:
public class SinglyLinkedList {
private static Node head;
private static int listSize;
private static class Node {
int value;
Node next;
Node(int i) {
value = i;
next = null;
}
}
public static void main(String[] args) {
head = null;
listSize = 0;
for (int i = 0; i < 10; i++) {
Node n = new Node(i);
if (head == null) {
head = n;
} else {
getLastNode(head).next = n;
}
listSize++;
}
printNodeValues(head);
Node revHead = reverseList(head);
printNodeValues(revHead);
}
private static Node reverseList(Node head) {
Node reverseHead = getLastNode(head);
Node reference = reverseHead;
while (listSize>0){
Node temp = getPreviousNode(reference, head);
Node last = getLastNode(reverseHead);
temp.next = null;
last.next = temp;
reference = temp;
listSize--;
}
return reverseHead;
}
private static Node getPreviousNode(Node reference, Node head) {
Node temp = head;
while (temp != null) {
if (temp.next == reference) {
break;
} else {
temp = temp.next;
}
}
return temp;
}
private static Node getLastNode(Node n) {
Node temp = n;
while (temp != null) {
if (temp.next == null) {
break;
} else {
temp = temp.next;
}
}
return temp;
}
public static void printNodeValues(Node h) {
while (h != null) {
System.out.print(h.value + " ");
h = h.next;
}
System.out.println();
}
}
The problem is with my reverseList(Node) method. When I run the program, I get the following error:
Exception in thread "main" java.lang.NullPointerException
at SinglyLinkedList.reverseList(SinglyLinkedList.java:44) -> temp = null;
at SinglyLinkedList.main(SinglyLinkedList.java:33) -> Node revHead = reverseList(head);
My printNodeValues works fine, and prints
0 1 2 3 4 5 6 7 8 9
and I'm trying to use reverseList to print
9 8 7 6 5 4 3 2 1 0.
There are many very bad things in your code. Worst of all : why is everything static ? What's the point of writing a list class that can be instantiated only once ?
Then, the size of the list should never be affected by a reverse operation, and you don't even need a counter since you just have to iterate over the list until you find a node which has no successor.
private static Node reverseList(Node head) {
Node res = null;
while (head != null) {
Node node = new Node(head.value);
node.next = res;
res = node;
head = head.next;
}
return res;
}
Your reverseList() method needs to skip the iteration when it has reached the first node in the original list because it's previous node doesn't exist. This first node has already be assigned as the next node (i.e. the last node in the reversed list) in the second last iteration (of your original loop).
private static Node reverseList(Node head) {
Node reverseHead = getLastNode(head);
Node reference = reverseHead;
int counter = listSize;
while ( counter > 1) {
Node temp = getPreviousNode(reference, head);
Node last = getLastNode(reverseHead);
temp.next = null;
last.next = temp;
reference = temp;
counter--;
}
return reverseHead;
}
Secondly, you shouldn't modify your listSize variable directly because the number of elements in the reversed list remains the same. Here, I'm storing it in a temporary counter first before iterating the list.
And, finally the reversed list should become your current head. Since, you've modified the linking between all the elements, it can only be traversed if your head now points to the new head.
printNodeValues(head);
head = reverseList(head);
printNodeValues(head);

Remove all occurrences of item from a Linked List

I've been working on this lab assignment for a few hours and can't understand why this code is not working. The question is to add the method int removeEvery(T item) that removes all occurrences of item and returns the number of removed items to a link list class that implements a link list interface.
This is my code: It removes some occurrences of the item, but not all of them.
public int removeEvery(T item){
int index = 0;
Node currentNode = firstNode;
for(int i = 1; i <= numberOfEntries; i++)
{
System.out.println(currentNode.getData());
if (item.equals(currentNode.getData())){
index++;
remove(i);}
else{
currentNode = currentNode.getNextNode();}
}
if(index != 0)
return index;
return -1;
}
Here is the remove method that was included in the LinkList class:
public T remove(int givenPosition)
{
T result = null; // return value
if ((givenPosition >= 1) && (givenPosition <= numberOfEntries))
{
assert !isEmpty();
if (givenPosition == 1) // case 1: remove first entry
{
result = firstNode.getData(); // save entry to be removed
firstNode = firstNode.getNextNode();
if (numberOfEntries == 1)
lastNode = null; // solitary entry was removed
}
else // case 2: givenPosition > 1
{
Node nodeBefore = getNodeAt(givenPosition - 1);
Node nodeToRemove = nodeBefore.getNextNode();
Node nodeAfter = nodeToRemove.getNextNode();
nodeBefore.setNextNode(nodeAfter); // disconnect the node to be removed
result = nodeToRemove.getData(); // save entry to be removed
if (givenPosition == numberOfEntries)
lastNode = nodeBefore; // last node was removed
} // end if
numberOfEntries--;
} // end if
return result; // return removed entry, or
// null if operation fails
} // end remove
There is something special with your linked list, you can access next element with current.getNextNode but you delete using the element index. You should look in the rest of your implementation how this index is managed. Does the first element have index 0 or 1 (you start your loop with 1). What happens to the indexes of all elements when you remove one. Do the elements know their index ?
You could use something like
int deletedNodes = 0;
int currentIndex = 0; // check if 1 or 0
currentNode = fist;
while(currentNode != null){ // I guess lastNode.getNextNode() is null
if(//should remove){
remove(currentIndex);
deletedNodes++
// probably no need to change the index as all element should have been shifted back one index
} else {
currentIndex++; // index changes only if no node was deleted
}
currentNode = currentNode.getNextNode(); // will work even if it was deleted
}
return deletedNodes;
I think the problem you have comes from remove(i).
When you remove the i-th element, the i+1-th element becomes the i-th and so on: every element is shifted. Therefore if you need to remove 2 elements in your list that are at index j and j+1, removing the j-th element calling remove(j) will shift the j+1-th element at the index j. Hence removing that second element requires calling remove(j) again, and not remove(j+1).
So you need to decrement i after removing.
Since your remove method actually decrements numberOfEntries, the condition on your while loop is properly updated. So all you need to do is replace
if (item.equals(currentNode.getData())) {
index++;
remove(i);
}
else {
currentNode = currentNode.getNextNode();
}
by
if (item.equals(currentNode.getData())) {
index++;
remove(i--);
}
// update the current node, whether removing it or not
currentNode = currentNode.getNextNode();
Iterator.remove()
This problem you are describing shows the usefulness of Iterator.remove() when using data structures from the JDK for going through an iterable collection and removing elements as you go through it.
After removing a node, as #Vakimshaar suggested, you need to decrement the i because the node at this index has been removed and there is a new node at the same index. In addition to that, you also need to update the currentNode reference as it would still be pointing to the node you've just removed, but it should really be pointing to the new node that has moved to this index.
So in the if (item.equals(currentNode.getData())){ block you need to do the following:
Node nextNode = currentNode.getNextNode();
index++;
remove(i--);
currentNode = nextNode;
With this, your code should correctly remove all occurrences.
Here is a Java Code to delete all occurrences of an item from a linked list :
public class LinkedList{
Node head;
class Node{
int data;
Node next;
Node(int d){data =d; next = null;}
}
public void push(int new_data){
Node new_node = new Node(new_data);
new_node.next = head;
head = new_node;
}
public void insertAfter(Node givenNode, int new_data){
if(givenNode == null)
System.out.println("Given node cannot be empty");
Node new_node = new Node(new_data);
new_node.next = givenNode.next;
givenNode.next = new_node;
}
public void append(int new_data){
Node new_node = new Node(new_data);
if(head == null)
head = new_node;
else{
Node last = head;
while(last.next != null)
last = last.next;
last.next = new_node;
}
}
public void printList(){
Node temp = head;
while(temp != null){
System.out.println(temp.data + " ");
temp = temp.next;
}
}
void deleteNode(int key){
// Store head node
Node temp = head, prev=null;
// If head node itself holds the key or multiple occurrences of key
while(temp != null && temp.data == key){
head = temp.next;
temp = head;
}
// Delete occurrences other than head
while(temp != null){
// Search for the key to be deleted, keep track of the
// previous node as we need to change 'prev.next'
while(temp != null && temp.data != key){
prev = temp;
temp = temp.next;
}
// If key was not present in linked list
if(temp == null) return;
// Unlink the node from linked list
prev.next = temp.next;
//Update Temp for next iteration of outer loop
temp = prev.next;
}
}
public static void main(String[] args){
LinkedList llist = new LinkedList();
llist.push(6);
llist.append(7);
llist.append(7);
llist.append(7);
llist.append(9);
llist.push(10);
llist.deleteNode(7);
llist.printList();
}
}
Output :
10
6
9

Categories