package com.freetymekiyan.algorithms.level.hard; import com.freetymekiyan.algorithms.utils.Utils.ListNode; /** * Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. * <p> * If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is. * <p> * You may not alter the values in the nodes, only nodes itself may be changed. * <p> * Only constant memory is allowed. * <p> * For example, * Given this linked list: 1->2->3->4->5 * <p> * For k = 2, you should return: 2->1->4->3->5 * <p> * For k = 3, you should return: 3->2->1->4->5 * <p> * Company Tags: Microsoft, Facebook * Tags: Linked List * Similar Problems: (E) Swap Nodes in Pairs */ public class ReverseNodesInKGroup { /** * Recursive. * Recurrence relation: * Reverse the current group and connect with reverseKGroup result on the rest of the list. * Implementation: * Try to find the head of the rest of the list by moving pointer. * Increment a counter for each step. * If counter != k, the group doesn't exist, return head directly. * Else reverse the rest of the list. * Store the node */ public ListNode reverseKGroup(ListNode head, int k) { ListNode restHead = head; int count = 0; while (restHead != null && count != k) { // Find the head of the rest of the list. restHead = restHead.next; count++; } if (count != k) { return head; } ListNode newHead = reverseKGroup(restHead, k); // Recurse on the rest of the list. // Head of reversed list. Init as the restHead which is the tail. while (count-- > 0) { // Reverse node k times. ListNode next = head.next; head.next = newHead; newHead = head; head = next; } return newHead; } /** * Iterative. * Divide linked list into two parts: * The first K nodes as a group, L1, might not exist. * The rest of the linked list, L2. * So first we move a pointer to the head of L2. * If we reach the end before K step, no more reverse, break and return. * If we find the head of L2, restHead, use it as a stop point for reverse. * Then we reverse the current group. */ public ListNode reverseKGroupB(ListNode head, int k) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode preHead = dummy; // Current group dummy. Or the tail of previous group. ListNode curHead = head; // Current group head. while (curHead != null) { ListNode restHead = curHead; int group = k; while (restHead != null && group > 0) { // Find nextHead. group--; restHead = restHead.next; } if (group > 0) { // Reach list end. break; } // Similar to reverse linked list. while (curHead.next != restHead) { // Ends at the head of remaining list. ListNode next = curHead.next.next; curHead.next.next = preHead.next; preHead.next = curHead.next; curHead.next = next; } preHead = curHead; // Move current dummy to the end of current group. curHead = curHead.next; // Move current head to the next group. } return dummy.next; } }