I have implemented a java code that reverses every k Node in the linked list and here is the code:
public class ReverseALinkedList {
public static void main(String[] args) {
int k = 2;
Node a = new Node(1);
Node b = new Node(2);
Node c = new Node(3);
Node d = new Node(4);
Node e = new Node(5);
Node f = new Node(6);
Node g = new Node(7);
Node h = new Node(8);
a.next = b;
b.next = c;
c.next = d;
d.next = e;
e.next = f;
f.next = g;
g.next = h;
a.printLinkedList();
Node head = reverseKLinkedList(a, k);
head.printLinkedList();
}
private static Node reverseKLinkedList(Node first, int k) {
Node current;
Node temp;
int count = 0;
current = null;
while (first != null && count < k) {
temp = first.next;
first.next = current;
current = first;
first = temp;
++count;
}
if (first != null) {
first.next = reverseKLinkedList(first, k);
}
return current;
}
static class Node {
public Node next;
public int value;
public Node(int value) {
this.value = value;
}
public void printLinkedList() {
Node head = this;
while (head.next != null) {
System.out.print(head.value + "->");
head = head.next;
}
System.out.print(head.value + "->null");
System.out.println();
}
}
}
When I execute the code with the following linked list:
1->2->3->4->5->6->null and k set to 2, I get an output as follows:
2->1->null
The rest of the nodes gets reversed (i.e., 4->3, 6->5), but they are not returned during the recursive call.
Could anybody please let me know how to fix this?
Another way of doing it is to ITERATE every K nodes and store it in a S stack like manner.
Wherein every S is stored in N newList in every K iteration.
private static Node reverseKLinkedList(Node first, int k){
Node newList, temp, current, walk, node;
int count;
node = first;
newList = null;
while(node != null) {
count = 0;
// stack the nodes to current until node is null or count is less than k
current = null;
while(node != null && count < k) {
temp = current;
current = new Node(node.value);
current.next = temp;
node = node.next;
count++;
}
if(newList == null) // if newList is empty then assign the current node
newList = current;
else {
// else traverse against the newList until it reaches
// the last node and then append the current not
walk = newList;
while(walk.next != null) walk = walk.next;
walk.next = current;
}
}
return newList;
}
As you are reversing the first one you are losing the reference to the next Node and therefore you lose the rest of the elements.
To implement this you should use recursion in order to store nodes or a stack(which is basically the same as recursion).
Proceed like this:
Store all the Nodes from the list in a stack.
For each node poped, the next elem is the top of the stack.
Repeat until no more nodes left.
Here is the recursive Java implementation
public static <T> LinearNode<T> reverseAlternateKNodes(LinearNode<T> node, int k) {
int count = 0;
LinearNode<T> curr=node, prev = null, next = null;
//reverse k nodes
while (curr != null && count < k) {
next = curr.next();
curr.next(prev);
prev = curr;
curr = next;
count ++;
}
// head should point to start of next k node
node.next(curr);
// skip nex knodes
count = 0;
while (curr != null && count < k- 1) {
curr = curr.next();
count ++;
}
// do it recursively
if (curr != null) {
curr.next(reverseAlternateKNodes(curr.next(), k));
}
return prev;
}
Here is the unit tests
#Test
public void reverseAlternateKNodes() {
LinearNode<Integer> head = buildLinkedList(1,2,3,4,5,6,7,8,9,10);
head = LinkedListUtil.reverseAlternateKNodes(head, 3);
assertLinkedList(head, 3,2,1,4,5,6,9,8,7,10);
}
public ListNode reverseKGroup(ListNode head, int k) {
ListNode curr = head;
int count = 0;
while(curr!=null && count!=k){
count++;
curr = curr.next;
}
if(count==k){
curr = reverseKGroup(curr,k);
while(count-->0){
ListNode temp = head.next;
head.next = curr;
curr = head;
head = temp;
}
head = curr;
}
return head;
}
Related
here's my code :
class Solution {
public int size (ListNode head)
{
int size = 0;
ListNode curr = head;
while (curr != null)
{
size ++;
curr = curr.next;
}
return size;
}
public ListNode swapNodes(ListNode head, int k) {
ListNode curr = head;
ListNode curr2 = head;
ListNode pre = null;
ListNode pre2 = null;
ListNode result = head;
for (int i = 1; i < k && curr != null; i ++)
{
pre = curr;
curr = curr.next;
}
int size = size(head);
for (int i = 0; i < (size - k) && curr2 != null; i ++)
{
pre2 = curr2;
curr2 = curr2.next;
}
ListNode tmp = curr.next;
ListNode tmp2 = curr2.next;
pre.next = curr2;
curr2.next = tmp;
pre2.next = curr;
curr.next = tmp2;
return head;
}
}
there seems to be an infinite loop in one of the cases and i can't fix it, can someone help please ?
for me everything works fine. Maybe you are using other inputs or initialising the List in a wrong way.
I added a method to your ListNode class to create the list in a fluent way:
public ListNode addListNode(int v) {
ListNode listNode = new ListNode(v);
next = listNode;
return listNode;
}
and a print Method to your Solution class to print the list.
public static void printList(ListNode head)
{
StringBuilder out = new StringBuilder();
ListNode curr = head;
while (curr != null)
{
out.append(curr.val).append(",");
curr = curr.next;
}
System.out.println(out);
}
Running it with this main method:
public static void main(String[] args) {
ListNode listNode = new ListNode(1);
ListNode currNode = listNode.addListNode(2);
for( int i = 3; i <= 10; i++) {
currNode = currNode.addListNode(i);
}
// you also could write listNode.addListNode(2).addListNode(3).addListNode(4) ...
printList(listNode);
System.out.println("SwapNodes");
ListNode swappedListNode = swapNodes(listNode, 2);
printList(swappedListNode);
}
it outputs
1,2,3,4,5,6,7,8,9,10,
SwapNodes
1,9,3,4,5,6,7,8,2,10,
So it seems to work as expected, no infinite loop. As I mentioned at the beginning feel free to add your main method and the way you are calling the swapNodes Method.
You can edit your question and add these informations..
In this linked list I am trying to delete a node and return the list after deleting the particular node. Here I am not using the Value to delete, I am using the position to delete that particular node. Here in my code the delete function seems to have no effect over the output. What am I doing wrong here?
import java.util.*;
class LinkedList{
Node head;
static class Node{
int data;
Node next;
Node(int d){
this.data = d;
next = null;
}
}
public LinkedList insert(LinkedList l, int data){
Node new_node = new Node(data);
if(l.head == null){
l.head = new_node;
}
else{
Node last = l.head;
while(last.next != null){
last = last.next;
}
last.next = new_node;
}
return l;
}
public LinkedList delete(LinkedList l, int position){
Node current = l.head;
if(position == 0){
current = current.next;
}
int index = 1;
while(index < position - 1){
current = current.next;
index++;
}
current = current.next.next;
Node iterating = l.head;
while(iterating != null){
System.out.print(iterating.data + " ");
iterating = iterating.next;
}
return l;
}
}
public class Main
{
public static void main(String[] args) {
LinkedList l = new LinkedList();
Scanner sc = new Scanner(System.in);
int number = sc.nextInt();
int position = sc.nextInt();
for(int i=0; i<number; i++){
int num = sc.nextInt();
l.insert(l,num);
}
l.delete(l,position);
}
}
current=current.next doesn't have any effect on the original LinkedList because with that line of code, you just change where the reference (named as current) points to.
Think about this way,
Node a = new Node()
Node b = new Node()
Node c = new Node()
a.next =b
a = c
These lines of code doesn't result in c being connected to b.
Change code to this:
if (position == 0) return l.head.next;
else {
Node head = l.head;
int index = 1;
Node itr = l.head;
while(index < position) {
itr = itr.next;
index++;
}
if(itr.next != null) itr.next = itr.next.next;
return head;
}
public LinkedList delete(LinkedList l, int position) {
Node previous = null;
Node current = l.head;
int index = 0;
while (current != null && index < position){
previous = current;
current = current.next;
index++;
}
if (current != null) {
if (previous == null) {
l.head = current.next;
} else {
previous.next = current.next;
}
}
System.out.print("[");
Node iterating = l.head;
while (iterating != null) {
System.out.print(iterating.data + ", ");
iterating = iterating.next;
}
System.out.println("]");
return l;
}
The problem in java is that to delete a node either the head must be changed to its next, or the previous node's next must be changed to current's next.
Then too current might become null, have reached the list's end, position > list length.
reverse second half linkedlist
example:
even number:
2->1->3->4->5->6->7->8 =====> 2->1->3->4->8->7->6->5 ;
odd number: 5->7->8->6->3->4->2 ======> 5->7->8->2->4->3->6, the
middle one also need be reversed
class ListNode
{
int val;
ListNode next;
ListNode(int x) { val = x; }
}
class ReverseRightHalfLinkedList
{
public static void main(String[] args)
{
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
ListNode res = reverse(node1);//line 31
// ListNode node = node1;
// while (node != null)
// {
// System.out.println(node.val);
// node = node.next;
// }
}
public static ListNode reverse(ListNode start)
{
int counter = 0;
ListNode node = start;
ListNode pre = start;
while (node!= null)
{
counter += 1;
node = node.next;
}
for (int i=0; i<counter/2; i++)
{
pre = start;
start = start.next;
}
ListNode cur = start;
if (counter%2 ==0)
{
while (cur != null)
{
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
}
else
{
pre = pre.next;
cur = start.next;
System.out.println(pre.val);
System.out.println(cur.val);
while (cur != null)
{
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
System.out.println("-----");
System.out.println(pre.val); // line 90
System.out.println(cur.val);
System.out.println("-----");
System.out.println();
}
}
return start;
}
}
Firstly, I got an error message.
Exception in thread "main" java.lang.NullPointerException at
ReverseRightHalfLinkedList.reverse(OA2.java:90) at
ReverseRightHalfLinkedList.main(OA2.java:31)
Secondly, I tried to print the order of reversed linked list, it is still in order. It was not reversed.
Please help me to figure out these two problems. Thanks a lot!
Basing on #passion's idea. I got a more concise code.
class ListNode
{
int val;
ListNode next;
ListNode(int x) { val = x; }
}
class ReverseRightHalfLinkedList
{
public static void main(String[] args)
{
ListNode node1 = new ListNode(2);
ListNode node2 = new ListNode(1);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(6);
ListNode node7 = new ListNode(7);
ListNode node8 = new ListNode(8);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = node7;
node7.next = node8;
ListNode res = reverse(node1);
ListNode node = node1;
while (node != null)
{
System.out.println(node.val);
node = node.next;
}
}
public static ListNode reverse(ListNode start)
{
int counter = 0;
ListNode node = start;
ListNode pre = start;
ListNode result = start;
while (node!= null)// for count how many elements in linked list
{
counter += 1;
node = node.next;
}
for (int i=0; i< (counter / 2) ; i++)//no matter counter is even or odd, when it divided by 2, the result is even
{
pre = start;
start = start.next;
}
ListNode temp = null;
ListNode preNext = null;// this variable is used to track the next val behind pre
// for example, 2->1->3->4->5->6->7->8
// at this moment, pre:4, start:5
// I treated 5->6->7->8 as an independent linkedlist
// I reversed the linkedlist
// Finally, set the pre node's next value to the reversed linkedlist's head
// The first half and second half have been connected together
while (start != null)
{
temp = start.next;
start.next = preNext;
preNext = start;
start = temp;
}
pre.next = preNext;
return start;
}
}
You need reverse right half list , so you need to save last node of the left half and the header of the list , so than when right half get reversed , you can link them with the left half and return the whole list .
I have change your reverse method :
public static ListNode reverse(ListNode start)
{
int counter = 0;
ListNode node = start;
ListNode pre = start;
ListNode result = start;
while (node!= null)
{
counter += 1;
node = node.next;
}
int end = counter % 2 == 0 ? counter / 2 : (counter- 1) / 2 ;
for (int i=0; i< end ; i++)
{
pre = start;
start = start.next;
}
ListNode tlist = null,temp ;
while(start != null){
temp = start.next;
if(tlist == null){
tlist = start;
start.next = null;
}else{
start.next = tlist;
tlist = start;
}
start = temp;
}
pre.next = tlist;
return start;
}
Hope this code helps you understand.
class MainClass {
public static void main(String args[]) {
Node head = new Node("Sameer");
//Adding data to my linked list
Node temp = addNode("Monica", head);
temp = addNode("Doug", temp);
temp = addNode("Eric", temp);
temp = addNode("Charlie", temp);
temp = addNode("Dan", temp);
temp = addNode("Enrique", temp);
temp = addNode("Ankitha", temp);
addNode("Chad", temp);
SolveMidLinkedList(head);
}
//method to add a node to the linked list
static Node addNode(String str, Node node) {
Node newNode = new Node(str);
node.link = newNode;
return newNode;
}
//method to reverse the right hald of the linkedlist
static void SolveMidLinkedList(Node head) {
int LinkedListSize = 0;
Node temp = head;
Node LastEle = null, MiddleEle = null, temp1 = null, temp2 = null;
//While loop to find the size of the linkedlist and also to find the last element in the linkedlist
while (temp != null) {
LastEle = temp;
temp = temp.link;
LinkedListSize++;
}
//Printing the names
temp = head;
System.out.println("Before rearranging the linked list");
while (temp != null) {
System.out.println(temp.name);
temp = temp.link;
}
//The main procedure
temp = head;
int iCount = 1;
while (temp != null) {
//Not changing the order of first half of the linked list
if (iCount <= (LinkedListSize / 2)) {
MiddleEle = temp;
} else {
//Reversing the order of second half(right side half) of the linked list.
temp2 = temp.link;
temp.link = temp1;
temp1 = temp;
}
temp = temp.link;
iCount++;
}
//At the end asssigning the middle element to the last element of the linked list.
MiddleEle.link = LastEle;
//Printing the names
temp = head;
System.out.println("After rearranging the linked list");
while (temp != null) {
System.out.println(temp.name);
temp = temp.link;
}
}
}
//General definition of Node in a linked list.
class Node {
Node link = null;
String name;
Node(String str) {
this.name = str;
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication2;
class LinkedList {
static Node head;
static class Node {
int data;
Node next;
Node(int d) {
data = d;
next = null;
}
}
Node rev(Node node) {
Node prev = null;
Node current = node;
Node next = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
node = prev;
return node;
}
Node reverse(Node node) {
int count =0;
Node doo = node;
Node mid_pre = node;
Node mid = node;
while(doo.next != null){
if((count & 1) == 1){
// mid_pre = mid;
mid = mid.next;
}
doo = doo.next;
count++;
}
// System.out.println(" midd ddddd :"+mid_pre.data+" "+mid.data);
mid.next = rev(mid.next);
return node;
}
void printList(Node node) {
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
}
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.head = new Node(1);
list.head.next = new Node(2);
list.head.next.next = new Node(3);
list.head.next.next.next = new Node(4);
list.head.next.next.next.next = new Node(5);
list.head.next.next.next.next.next = new Node(6);
//// 1 2 3 4 5 6
System.out.println("Given Linked list");
list.printList(head);
head = list.reverse(head);
System.out.println("");
System.out.println("Reversed linked list ");
list.printList(head);
}
}
Why not do something very straightforward. We know the size of the list. We can use list.get(counter) to iterate from the end to the centre. There was a bit of challenge when the list size was even or odd but its doable.
public static void reverseFromEndToCentre() {
List list = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
int midOfList = (int)Math.ceil(list.size() / 2);
int lenthOfList = list.size();
int counterFirstHalf =0;
while(counterFirstHalf<midOfList){
System.out.println(list.get(counterFirstHalf));
counterFirstHalf++;
}
int counterSecondHalf = lenthOfList;
while( counterSecondHalf > counterFirstHalf){
counterSecondHalf--;
System.out.println(list.get(counterSecondHalf ));
}
}
Here's a way to reverse second half(right) of linked list.
#include<stdio.h>
#include<stdlib.h>
struct Node{
int data;
struct Node* next;
};
void append(struct Node** head_ref, int new_data)
{
struct Node* new_node=(struct Node*)malloc(sizeof(struct Node));
new_node->data=new_data;
new_node->next=NULL;
struct Node* last=*head_ref;
if(*head_ref==NULL){
*head_ref=new_node;
return;
}
while(last->next!=NULL)
last=last->next;
last->next=new_node;
return;
}
int display(struct Node* n)
{
int m=0;
printf("\n");
while(n!=NULL)
{
printf(" %d ",n->data);
n=n->next;
m=m+1;
}
return m;
}
void reverse(struct Node** head_ref, int mid)
{
if(*head_ref==NULL)
{
printf("\nEmpty List cannot be reversed");
return;
}
struct Node* last=*head_ref;
struct Node* second_last;
struct Node* beg=*head_ref;
int c=1;
while(c<=mid){
second_last=last;
last=last->next;
c=c+1;
}
struct Node* prev=NULL;
struct Node* current=last;
struct Node* next;
while(current != NULL)
{
next=current->next;
current->next=prev;
prev=current;
current=next;
}
*head_ref=beg;
second_last->next=prev;
}
int main()
{
int size;
struct Node* head=NULL;
int i,mid;
for(i=0;i<11;i++)
{
append(&head,rand()%19 +1);
}
size=display(head);
printf("\n Size of linked list: %d",size);
if(size%2==0)
mid=(size+1)/2;
else
mid=size/2;
reverse(&head, mid);
display(head);
return 0;
}
I am writing a priority queue using doubly linked list with sentinels
class Node {
protected Node next;
protected Node prev;
protected int value;
public Node() {
}
public Node(int value) {
this.value = value;
}
}
This is my node class where I have set a condition that the Value lies between 0 and 11111 for ease in sorting.
public class someName {
protected Node firstSentinel;
protected Node lastSentinel;
public someName() {
firstSentinel = new Node();
lastSentinel = new Node();
firstSentinel.value = 11111;
lastSentinel.value = 0;
firstSentinel.prev = null;
firstSentinel.next = lastSentinel;
lastSentinel.prev = firstSentinel;
lastSentinel.next = null;
}
public void enQueue(Node x) {
if (firstSentinel.next == lastSentinel)// list is empty
{
firstSentinel.next = x;
x.prev = firstSentinel;
x.next = lastSentinel;
lastSentinel.prev = x;
} else {
Node temp = x;
Node curr = firstSentinel.next;
while (curr != lastSentinel && temp.value <= curr.value) {
curr = curr.next;
}
Node tempCurr = curr;
temp.next = tempCurr;
temp.prev = tempCurr.prev;
tempCurr.prev = temp;
tempCurr.prev.next = temp;
}
}
public Node deQueue() {
if (firstSentinel.next == lastSentinel) {
return null;
} else {
Node temp = new Node();
temp = firstSentinel.next;
firstSentinel.next = temp.next;
temp.next.prev = firstSentinel;
return temp;
}
}
public void printt() {
Node temp = new Node();
temp = firstSentinel.next;
while (temp != lastSentinel) {
System.out.println(temp.value);
temp = temp.next;
}
}
public static void main(String[] args) {
someName PQ = new someName();
Node a = new Node(2);
PQ.enQueue(a);
PQ.printt();
Node aa = new Node(456);
PQ.enQueue(aa);
Node aaa = new Node(123);
PQ.enQueue(aaa);
PQ.printt();
Node aaaa = new Node(6);
PQ.enQueue(aaaa);
PQ.printt();
Node aaaaa = new Node(1123);
PQ.enQueue(aaaaa);
PQ.printt();
}
}
When the program is run it just outputs twos. Which makes be believe that only 1 node(first node especially) is getting inserted. In this priority queue i am interested in descending order and as such the first sentinel value is being set to 11111 and last's is being set to 0. I think I am doing something stupid in enqueue. I will be glad if someone points me in the right direction.
Your enQueue method appears to be flawed:
public void enQueue(Node x) {
if (firstSentinel.next == lastSentinel)// list is empty
{
firstSentinel.next = x;
x.prev = firstSentinel;
x.next = lastSentinel;
lastSentinel.prev = x;
} else {
Node temp = x;
Node curr = firstSentinel.next;
while (curr != lastSentinel && temp.value <= curr.value) {
curr = curr.next;
}
Node tempCurr = curr;
temp.next = tempCurr;
temp.prev = tempCurr.prev;
tempCurr.prev = temp;
// Think very carefully what this next line does.
// You've just overwritten tempCurr.prev with temp.
// This means you've now assigned temp.next = temp
// That's going to create a cycle.
tempCurr.prev.next = temp;
}
}
If you simply reorder that line to above the assignment, then it may work as you intend:
public void enQueue(Node x) {
if (firstSentinel.next == lastSentinel)// list is empty
{
firstSentinel.next = x;
x.prev = firstSentinel;
x.next = lastSentinel;
lastSentinel.prev = x;
} else {
Node temp = x;
Node curr = firstSentinel.next;
while (curr != lastSentinel && temp.value <= curr.value) {
curr = curr.next;
}
Node tempCurr = curr;
temp.next = tempCurr;
temp.prev = tempCurr.prev;
tempCurr.prev.next = temp;
// Note here that the assignment to tempCurr.prev happens
// after the assignment to tempCurr.prev.next
tempCurr.prev = temp;
}
}
Note that you can also simplify your logic in enQueue dramatically by dropping the if entirely. Your current else case can handle both the empty and non-empty cases (at least once you've fixed the bug I've pointed out.) You also don't need the temp variable.
public void enQueue(Node x) {
Node curr = firstSentinel.next;
while (curr != lastSentinel && x.value <= curr.value) {
curr = curr.next;
}
Node tempCurr = curr;
x.next = tempCurr;
x.prev = tempCurr.prev;
tempCurr.prev.next = x;
tempCurr.prev = x;
}
I recently encounter an algorithm problem:
Reverse a singly-linked list in blocks of k in place. An iterative approach is preferred.
The first block of the resulting list should be maximal with regards to k. If the list contains n elements, the last block will either be full or contain n mod k elements.
For example:
k = 2, list = [1,2,3,4,5,6,7,8,9], the reversed list is [8,9,6,7,4,5,2,3,1]
k = 3, list = [1,2,3,4,5,6,7,8,9], the reversed list is [7,8,9,4,5,6,1,2,3]
My code is shown as below.
Is there an O(n) algorithm that doesn't use a stack or extra space?
public static ListNode reverse(ListNode list, int k) {
Stack<ListNode> stack = new Stack<ListNode>();
int listLen = getLen(list);
int firstBlockSize = listLen % k;
ListNode start = list;
if (firstBlockSize != 0) {
start = getBlock(stack, start, firstBlockSize);
}
int numBlock = (listLen) / k;
for (int i = 0; i < numBlock; i++) {
start = getBlock(stack, start, k);
}
ListNode dummy = new ListNode(0);
ListNode cur = dummy;
while (!stack.empty()) {
cur.next = stack.peek();
cur = stack.pop();
while (cur.next != null) {
cur = cur.next;
}
}
return dummy.next;
}
public static ListNode getBlock(Stack<ListNode> stack, ListNode start, int blockSize) {
ListNode end = start;
while (blockSize > 1) {
end = end.next;
blockSize--;
}
ListNode temp = end.next;
end.next = null;
stack.push(start);
return temp;
}
public static int getLen(ListNode list) {
ListNode iter = list;
int len = 0;
while (iter != null) {
len++;
iter = iter.next;
}
return len;
}
This can be done in O(n) time using O(1) space as follows:
Reverse the entire list.
Reverse the individual blocks.
Both can be done using something very similar to the standard way to reverse a singly linked-list and the overall process resembles reversing the ordering of words in a string.
Reversing only a given block is fairly easily done by using a length variable.
The complication comes in when we need to move from one block to the next. The way I achieved this was by having the reverse function return both the first and last nodes and having the last node point to the next node in our original linked-list. This is necessary because the last node's next pointer needs to be updated to point to the first node our next reverse call returns (we don't know what it will need to point to before that call completes).
For simplicity's sake, I used a null start node in the code below (otherwise I would've needed to cater for the start node specifically, which would've complicated the code).
class Test
{
static class Node<T>
{
Node next;
T data;
Node(T data) { this.data = data; }
#Override
public String toString() { return data.toString(); }
}
// reverses a linked-list starting at 'start', ending at min(end, len-th element)
// returns {first element, last element} with (last element).next = (len+1)-th element
static <T> Node<T>[] reverse(Node<T> start, int len)
{
Node<T> current = start;
Node<T> prev = null;
while (current != null && len > 0)
{
Node<T> temp = current.next;
current.next = prev;
prev = current;
current = temp;
len--;
}
start.next = current;
return new Node[]{prev, start};
}
static <T> void reverseByBlock(Node<T> start, int k)
{
// reverse the complete list
start.next = reverse(start.next, Integer.MAX_VALUE)[0];
// reverse the individual blocks
Node<T>[] output;
Node<T> current = start;
while (current.next != null)
{
output = reverse(current.next, k);
current.next = output[0];
current = output[1];
}
}
public static void main(String[] args)
{
//Scanner scanner = new Scanner(System.in);
Scanner scanner = new Scanner("3 9 1 2 3 4 5 6 7 8 9\n" +
"2 9 1 2 3 4 5 6 7 8 9");
while (scanner.hasNextInt())
{
int k = scanner.nextInt();
// read the linked-list from console
Node<Integer> start = new Node<>(null);
Node<Integer> current = start;
int n = scanner.nextInt();
System.out.print("Input: ");
for (int i = 1; i <= n; i++)
{
current.next = new Node<>(scanner.nextInt());
current = current.next;
System.out.print(current.data + " ");
}
System.out.println("| k = " + k);
// reverse the list
reverseByBlock(start, k);
// display the list
System.out.print("Result: ");
for (Node<Integer> node = start.next; node != null; node = node.next)
System.out.print(node + " ");
System.out.println();
System.out.println();
}
}
}
This outputs:
Input: 1 2 3 4 5 6 7 8 9 | k = 3
Result: 7 8 9 4 5 6 1 2 3
Input: 1 2 3 4 5 6 7 8 9 | k = 2
Result: 8 9 6 7 4 5 2 3 1
Live demo.
Here is an iterative way of doing it... you read my full explanation here
Node reverseListBlocks1(Node head, int k) {
if (head == null || k <= 1) {
return head;
}
Node newHead = head;
boolean foundNewHead = false;
// moves k nodes through list each loop iteration
Node mover = head;
// used for reversion list block
Node prev = null;
Node curr = head;
Node next = null;
Finish: while (curr != null) {
// move the mover just after the block we are reversing
for (int i = 0; i < k; i++) {
// if there are no more reversals, finish
if (mover == null) {
break Finish;
}
mover = mover.next;
}
// reverse the block and connect its tail to the rest of
// the list (at mover's position)
prev = mover;
while (curr != mover) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
// establish the new head, if we didn't yet
if (!foundNewHead) {
newHead = prev;
foundNewHead = true;
}
// connects previous block's head to the rest of the list
// move the head to the tail of the reversed block
else {
head.next = prev;
for (int i = 0; i < k; i++) {
head = head.next;
}
}
}
return newHead;
}
The easiest way to reverse the single linked list is as follows.
private void reverse(Node node)
{
Node current = Node;
Node prev = null;
Node next = null;
if(node == null || node.next == null)
{
return node;
}
while(current != null)
{
next = current.next;
//swap
current.next = prev;
prev = current;
current = next;
}
node.next = current;
}
This section contains multiple Single Linked List Operation
import java.util.Scanner;
import java.util.Stack;
public class AddDigitPlusLL {
Node head = null;
int len =0;
static class Node {
int data;
Node next;
Node(int data) {
this.data = data;
this.next = null;
}
}
public void insertFirst(int data) {
Node newNode = new Node(data);
if (head != null)
newNode.next = head;
head = newNode;
}
public void insertLast(int data) {
Node temp = head;
Node newNode = new Node(data);
if (temp == null)
head = newNode;
else {
Node previousNode = null;
while (temp != null) {
previousNode = temp;
temp = temp.next;
}
previousNode.next = newNode;
}
}
public Long getAllElementValue() {
Long val = 0l;
Node temp=head;
while(temp !=null) {
if(val == 0)
val=(long) temp.data;
else
val=val*10+temp.data;
temp = temp.next;
}
System.out.println("value is :" + val);
return val;
}
public void print(String printType) {
System.out.println("----------- :"+ printType +"----------- ");
Node temp = head;
while (temp != null) {
System.out.println(temp.data + " --> ");
temp = temp.next;
}
}
public void generateList(Long val) {
head = null;
while(val > 0) {
int remaining = (int) (val % 10);
val = val/10;
insertFirst(remaining);
}
}
public void reverseList(Long val) {
head =null;
while(val >0) {
int remaining = (int) (val % 10);
val = val/10;
insertLast(remaining);
}
}
public void lengthRecursive(Node temp) {
if(temp != null) {
len++;
lengthRecursive(temp.next);
}
}
public void reverseUsingStack(Node temp) {
Stack<Integer> stack = new Stack<Integer>();
while(temp != null) {
stack.push(temp.data);
temp = temp.next;
}
head = null;
while(!stack.isEmpty()) {
int val = stack.peek();
insertLast(val);
stack.pop();
}
print(" Reverse Using Stack");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s = new Scanner(System.in);
AddDigitPlusLL sll = new AddDigitPlusLL();
sll.insertFirst(5);
sll.insertFirst(9);
sll.insertLast(8);
sll.print("List Iterate");
Long val = sll.getAllElementValue();
System.out.println("Enter the digit to add");
Long finalVal = val +s.nextInt();
s.close();
sll.generateList(finalVal);
sll.print("Add int with List Value");
sll.reverseList(finalVal);
sll.print("Reverse the List");
sll.lengthRecursive(sll.head);
System.out.println("Length with Recursive :"+ sll.len);
sll.print("Before call stack reverse method");
sll.reverseUsingStack(sll.head);
}
}