Reverse Nodes in k-Group
Problem Statement
Section titled “Problem Statement”Given the head of a linked list, reverse the nodes of the list k at a time, and return the modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes, in the end, should remain as is.
You may not alter the values in the list’s nodes, only nodes themselves may be changed.
Examples
Section titled “Examples”| Input | k | Output | Explanation |
|---|---|---|---|
[1, 2, 3, 4, 5] | 2 | [2, 1, 4, 3, 5] | Reverse (1, 2) and (3, 4); leave 5 as is |
[1, 2, 3, 4, 5] | 3 | [3, 2, 1, 4, 5] | Reverse (1, 2, 3); leave (4, 5) as is |
[1] | 1 | [1] | Only one node, no change |
[1, 2] | 2 | [2, 1] | Reverse the only group of 2 |
Constraints
Section titled “Constraints”- The number of nodes in the list is
n. 1 <= k <= n <= 50000 <= Node.val <= 1000
Real-World Applications
Section titled “Real-World Applications”Complexity Comparison
Section titled “Complexity Comparison”| Approach | Time | Space | Best When |
|---|---|---|---|
| Iterative | O(n) | O(1) | General case — no recursion overhead, more intuitive |
| Recursive | O(n) | O(n/k) | Learning recursion, practicing elegant divide-and-conquer |
* Space refers to the call stack. The iterative approach uses only a few pointers.
Which approach should you learn first?
Section titled “Which approach should you learn first?”- Pick Iterative for the most direct and efficient solution — it clearly shows group boundaries and reversal.
- Pick Recursive if you want to practice thinking of the problem as smaller subproblems, each handling one group independently.
Approach 1: Iterative with Group Reversal
Section titled “Approach 1: Iterative with Group Reversal”Process the list in groups of k nodes. For each group:
- Identify the boundaries of the group (k-th node and the node after it)
- Reverse the pointers within the group
- Link the reversed group back to the previous group
- Move forward to the next group
The key is using a dummy node as the head to simplify edge cases and tracking prevGroup to maintain links between groups.
Step-by-step Example
Section titled “Step-by-step Example”Input: [1, 2, 3, 4, 5], k = 2
| Step | Action | State |
|---|---|---|
| Check group 1 | Group (1, 2) exists (2 nodes) | Group boundaries identified |
| Reverse group 1 | Reverse pointers: 1 ← 2 | List becomes 2 → 1 → 3 → 4 → 5 |
| Link backward | Connect dummy to reversed group | dummy → 2 → 1 → … |
| Check group 2 | Group (3, 4) exists (2 nodes) | Next group boundaries identified |
| Reverse group 2 | Reverse pointers: 3 ← 4 | List becomes … → 4 → 3 → 5 |
| Link backward | Connect group 1 to reversed group 2 | … → 1 → 4 → 3 → 5 |
| Check group 3 | Only 1 node (5) left, k=2 | Stop (less than k nodes) |
| Final result | Return dummy.next | [2, 1, 4, 3, 5] ✓ |
Animated walkthrough
Use Next or Autoplay to see how each group is identified, reversed, and reconnected.
Pseudocode
Section titled “Pseudocode”function reverseKGroupIterative(head, k): dummy = ListNode(0) dummy.next = head prevGroup = dummy
while True: kthNode = getKthNode(prevGroup, k + 1) if not kthNode: break
groupStart = prevGroup.next groupEnd = kthNode nextGroupStart = groupEnd.next
// Reverse the group from groupStart to groupEnd prev = nextGroupStart curr = groupStart while curr != nextGroupStart: nextTemp = curr.next curr.next = prev prev = curr curr = nextTemp
// Link previous group to reversed current group prevGroup.next = groupEnd prevGroup = groupStart
return dummy.next
function getKthNode(node, k): while node and k > 1: node = node.next k -= 1 return nodeSolution Code
Section titled “Solution Code”from typing import Optional
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next
def reverse_k_group_iterative(head: Optional[ListNode], k: int) -> Optional[ListNode]: """ Reverse nodes in k-group iteratively.
Approach: Reverse each group of k nodes in-place using iteration. - Find the k-th node to determine the group boundary - Reverse the group from current to k-th node - Link the reversed group back to the previous group - Move to the next group and repeat
Time: O(n) - visit each node once Space: O(1) - only pointers, no extra structures """ # Check if there are at least k nodes to reverse def get_kth_node(node, k): """Find the k-th node starting from 'node'.""" while node and k > 1: node = node.next k -= 1 return node
# Dummy node to simplify logic (no need to handle head specially) dummy = ListNode(0) dummy.next = head
prev_group = dummy # Tracks the node before the current group
while True: # Check if there are at least k nodes remaining kth_node = get_kth_node(prev_group, k + 1) if not kth_node: break
# Mark the start and end of the current group group_start = prev_group.next group_end = kth_node
# Save the next group's start (before we reverse the current group) next_group_start = group_end.next
# Reverse the current group # We reverse from group_start to group_end (inclusive) prev = next_group_start # The node after group_end becomes the new tail curr = group_start
while curr != next_group_start: next_temp = curr.next curr.next = prev prev = curr curr = next_temp
# Link the previous group to the reversed current group prev_group.next = group_end prev_group = group_start
return dummy.next
# Test casesdef create_linked_list(values): """Helper to create a linked list from a list of values.""" if not values: return None head = ListNode(values[0]) current = head for val in values[1:]: current.next = ListNode(val) current = current.next return head
def linked_list_to_list(head): """Helper to convert linked list to list for easy comparison.""" result = [] while head: result.append(head.val) head = head.next return result
# Testhead1 = create_linked_list([1, 2, 3, 4, 5])result1 = reverse_k_group_iterative(head1, 2)print(linked_list_to_list(result1)) # [2, 1, 4, 3, 5]
head2 = create_linked_list([1, 2, 3, 4, 5])result2 = reverse_k_group_iterative(head2, 3)print(linked_list_to_list(result2)) # [3, 2, 1, 4, 5]
head3 = create_linked_list([1])result3 = reverse_k_group_iterative(head3, 1)print(linked_list_to_list(result3)) # [1]#include <iostream>#include <vector>using namespace std;
struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {}};
ListNode* reverseKGroupIterative(ListNode* head, int k) { /** * Reverse nodes in k-group iteratively. * * Approach: Reverse each group of k nodes in-place using iteration. * - Find the k-th node to determine the group boundary * - Reverse the group from current to k-th node * - Link the reversed group back to the previous group * - Move to the next group and repeat * * Time: O(n) - visit each node once * Space: O(1) - only pointers, no extra structures */
auto get_kth_node = [](ListNode* node, int k) -> ListNode* { while (node && k > 1) { node = node->next; k--; } return node; };
// Dummy node to simplify logic ListNode* dummy = new ListNode(0); dummy->next = head;
ListNode* prev_group = dummy;
while (true) { // Check if there are at least k nodes remaining ListNode* kth_node = get_kth_node(prev_group, k + 1); if (!kth_node) { break; }
// Mark the start and end of the current group ListNode* group_start = prev_group->next; ListNode* group_end = kth_node;
// Save the next group's start ListNode* next_group_start = group_end->next;
// Reverse the current group ListNode* prev = next_group_start; ListNode* curr = group_start;
while (curr != next_group_start) { ListNode* next_temp = curr->next; curr->next = prev; prev = curr; curr = next_temp; }
// Link the previous group to the reversed current group prev_group->next = group_end; prev_group = group_start; }
ListNode* result = dummy->next; delete dummy; return result;}
// Helper functions for testingListNode* createList(const vector<int>& values) { if (values.empty()) return nullptr; ListNode* head = new ListNode(values[0]); ListNode* current = head; for (int i = 1; i < values.size(); i++) { current->next = new ListNode(values[i]); current = current->next; } return head;}
void printList(ListNode* head) { cout << "["; while (head) { cout << head->val; if (head->next) cout << ", "; head = head->next; } cout << "]" << endl;}
// Testint main() { ListNode* head1 = createList({1, 2, 3, 4, 5}); printList(reverseKGroupIterative(head1, 2)); // [2, 1, 4, 3, 5]
ListNode* head2 = createList({1, 2, 3, 4, 5}); printList(reverseKGroupIterative(head2, 3)); // [3, 2, 1, 4, 5]
ListNode* head3 = createList({1}); printList(reverseKGroupIterative(head3, 1)); // [1]
return 0;}import java.util.*;
class ListNode { int val; ListNode next;
ListNode(int val) { this.val = val; this.next = null; }}
public class ReverseNodesInKGroupIterative { /** * Reverse nodes in k-group iteratively. * * Approach: Reverse each group of k nodes in-place using iteration. * - Find the k-th node to determine the group boundary * - Reverse the group from current to k-th node * - Link the reversed group back to the previous group * - Move to the next group and repeat * * Time: O(n) - visit each node once * Space: O(1) - only pointers, no extra structures */
private static ListNode getKthNode(ListNode node, int k) { while (node != null && k > 1) { node = node.next; k--; } return node; }
public static ListNode reverseKGroup(ListNode head, int k) { // Dummy node to simplify logic ListNode dummy = new ListNode(0); dummy.next = head;
ListNode prevGroup = dummy;
while (true) { // Check if there are at least k nodes remaining ListNode kthNode = getKthNode(prevGroup, k + 1); if (kthNode == null) { break; }
// Mark the start and end of the current group ListNode groupStart = prevGroup.next; ListNode groupEnd = kthNode;
// Save the next group's start ListNode nextGroupStart = groupEnd.next;
// Reverse the current group ListNode prev = nextGroupStart; ListNode curr = groupStart;
while (curr != nextGroupStart) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; }
// Link the previous group to the reversed current group prevGroup.next = groupEnd; prevGroup = groupStart; }
return dummy.next; }
// Helper functions for testing private static ListNode createList(int[] values) { if (values.length == 0) return null; ListNode head = new ListNode(values[0]); ListNode current = head; for (int i = 1; i < values.length; i++) { current.next = new ListNode(values[i]); current = current.next; } return head; }
private static void printList(ListNode head) { System.out.print("["); while (head != null) { System.out.print(head.val); if (head.next != null) System.out.print(", "); head = head.next; } System.out.println("]"); }
// Test public static void main(String[] args) { ListNode head1 = createList(new int[]{1, 2, 3, 4, 5}); printList(reverseKGroup(head1, 2)); // [2, 1, 4, 3, 5]
ListNode head2 = createList(new int[]{1, 2, 3, 4, 5}); printList(reverseKGroup(head2, 3)); // [3, 2, 1, 4, 5]
ListNode head3 = createList(new int[]{1}); printList(reverseKGroup(head3, 1)); // [1] }}/** * Definition for singly-linked list node. */class ListNode { constructor(val = 0, next = null) { this.val = val; this.next = next; }}
/** * Reverse nodes in k-group iteratively. * * Approach: Reverse each group of k nodes in-place using iteration. * - Find the k-th node to determine the group boundary * - Reverse the group from current to k-th node * - Link the reversed group back to the previous group * - Move to the next group and repeat * * Time: O(n) - visit each node once * Space: O(1) - only pointers, no extra structures * * @param {ListNode} head * @param {number} k * @return {ListNode} */var reverseKGroup = function (head, k) { const getKthNode = (node, k) => { while (node && k > 1) { node = node.next; k--; } return node; };
// Dummy node to simplify logic const dummy = new ListNode(0); dummy.next = head;
let prevGroup = dummy;
while (true) { // Check if there are at least k nodes remaining const kthNode = getKthNode(prevGroup, k + 1); if (!kthNode) { break; }
// Mark the start and end of the current group const groupStart = prevGroup.next; const groupEnd = kthNode;
// Save the next group's start const nextGroupStart = groupEnd.next;
// Reverse the current group let prev = nextGroupStart; let curr = groupStart;
while (curr !== nextGroupStart) { const nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; }
// Link the previous group to the reversed current group prevGroup.next = groupEnd; prevGroup = groupStart; }
return dummy.next;};
// Helper functions for testingconst createList = (values) => { if (values.length === 0) return null; let head = new ListNode(values[0]); let current = head; for (let i = 1; i < values.length; i++) { current.next = new ListNode(values[i]); current = current.next; } return head;};
const printList = (head) => { const result = []; while (head) { result.push(head.val); head = head.next; } console.log("[" + result.join(", ") + "]");};
// Testlet head1 = createList([1, 2, 3, 4, 5]);printList(reverseKGroup(head1, 2)); // [2, 1, 4, 3, 5]
let head2 = createList([1, 2, 3, 4, 5]);printList(reverseKGroup(head2, 3)); // [3, 2, 1, 4, 5]
let head3 = createList([1]);printList(reverseKGroup(head3, 1)); // [1]use std::cell::RefCell;use std::rc::Rc;
#[derive(Debug, PartialEq, Eq)]pub struct ListNode { pub val: i32, pub next: Option<Box<ListNode>>,}
impl ListNode { #[inline] fn new(val: i32) -> Self { ListNode { next: None, val } }}
/** * Reverse nodes in k-group iteratively. * * Approach: Reverse each group of k nodes in-place using iteration. * - Find the k-th node to determine the group boundary * - Reverse the group from current to k-th node * - Link the reversed group back to the previous group * - Move to the next group and repeat * * Time: O(n) - visit each node once * Space: O(1) - only pointers, no extra structures */pub fn reverse_k_group(head: Option<Box<ListNode>>, k: i32) -> Option<Box<ListNode>> { fn get_kth_node(mut node: Option<&mut Box<ListNode>>, k: i32) -> Option<&mut Box<ListNode>> { let mut k = k; loop { match node { Some(n) if k > 1 => { k -= 1; node = n.next.as_mut().map(|next| next); } Some(n) => return Some(n), None => return None, } } }
let mut dummy = Box::new(ListNode::new(0)); dummy.next = head;
let mut prev_group = &mut dummy;
loop { // Check if there are at least k nodes remaining let kth_node = { let mut curr = &mut prev_group.next; let mut count = k; while count > 1 && curr.is_some() { curr = &mut curr.as_mut().unwrap().next; count -= 1; } if curr.is_some() && count == 1 { curr.is_some() } else { false } };
if !kth_node { break; }
// Manually reverse k nodes let mut group_start = prev_group.next.take(); let mut kth = &mut group_start; for _ in 1..k { kth = &mut kth.as_mut().unwrap().next; }
let next_group_head = kth.as_mut().unwrap().next.take();
// Perform reversal let mut prev = next_group_head; let mut curr = group_start;
for _ in 0..k { let next_tmp = curr.as_mut().unwrap().next.take(); curr.as_mut().unwrap().next = prev; prev = curr; curr = next_tmp; }
let group_end = prev; prev_group.next = group_end;
// Move prev_group forward for _ in 0..k { prev_group = &mut prev_group.next.as_mut().unwrap(); } }
dummy.next}
fn create_list(values: Vec<i32>) -> Option<Box<ListNode>> { if values.is_empty() { return None; } let mut head = Box::new(ListNode::new(values[0])); let mut current = &mut head; for i in 1..values.len() { current.next = Some(Box::new(ListNode::new(values[i]))); current = current.next.as_mut().unwrap(); } Some(head)}
fn print_list(head: Option<Box<ListNode>>) { let mut result = vec![]; let mut current = head; while let Some(node) = current { result.push(node.val.to_string()); current = node.next; } println!("[{}]", result.join(", "));}
fn main() { let head1 = create_list(vec![1, 2, 3, 4, 5]); print_list(reverse_k_group(head1, 2)); // [2, 1, 4, 3, 5]
let head2 = create_list(vec![1, 2, 3, 4, 5]); print_list(reverse_k_group(head2, 3)); // [3, 2, 1, 4, 5]
let head3 = create_list(vec![1]); print_list(reverse_k_group(head3, 1)); // [1]}package main
import "fmt"
type ListNode struct { Val int Next *ListNode}
/** * Reverse nodes in k-group iteratively. * * Approach: Reverse each group of k nodes in-place using iteration. * - Find the k-th node to determine the group boundary * - Reverse the group from current to k-th node * - Link the reversed group back to the previous group * - Move to the next group and repeat * * Time: O(n) - visit each node once * Space: O(1) - only pointers, no extra structures */func reverseKGroup(head *ListNode, k int) *ListNode { getKthNode := func(node *ListNode, k int) *ListNode { for node != nil && k > 1 { node = node.Next k-- } return node }
// Dummy node to simplify logic dummy := &ListNode{Val: 0, Next: head} prevGroup := dummy
for { // Check if there are at least k nodes remaining kthNode := getKthNode(prevGroup, k+1) if kthNode == nil { break }
// Mark the start and end of the current group groupStart := prevGroup.Next groupEnd := kthNode
// Save the next group's start nextGroupStart := groupEnd.Next
// Reverse the current group prev := nextGroupStart curr := groupStart
for curr != nextGroupStart { nextTemp := curr.Next curr.Next = prev prev = curr curr = nextTemp }
// Link the previous group to the reversed current group prevGroup.Next = groupEnd prevGroup = groupStart }
return dummy.Next}
// Helper functions for testingfunc createList(values []int) *ListNode { if len(values) == 0 { return nil } head := &ListNode{Val: values[0]} current := head for i := 1; i < len(values); i++ { current.Next = &ListNode{Val: values[i]} current = current.Next } return head}
func printList(head *ListNode) { fmt.Print("[") first := true for head != nil { if !first { fmt.Print(", ") } fmt.Print(head.Val) first = false head = head.Next } fmt.Println("]")}
func main() { head1 := createList([]int{1, 2, 3, 4, 5}) printList(reverseKGroup(head1, 2)) // [2, 1, 4, 3, 5]
head2 := createList([]int{1, 2, 3, 4, 5}) printList(reverseKGroup(head2, 3)) // [3, 2, 1, 4, 5]
head3 := createList([]int{1}) printList(reverseKGroup(head3, 1)) // [1]}Approach 2: Recursive with Self-Similar Groups
Section titled “Approach 2: Recursive with Self-Similar Groups”Recursion allows us to think of the problem as:
- Reverse the first k nodes and get the new head of this group
- Recursively solve the rest of the list (starting from the (k+1)-th node)
- Connect the tail of the current group to the result of the recursive call
This approach cleanly separates each group’s processing and is conceptually elegant, though it uses O(n/k) stack space.
Step-by-step Example
Section titled “Step-by-step Example”Input: [1, 2, 3, 4, 5], k = 2
| Recursion Level | Group | Action | Returns |
|---|---|---|---|
| 1 | (1, 2) → (3, 4, 5) | Reverse (1, 2); recursively solve (3, 4, 5) | head: 2, tail: 1 |
| 2 | (3, 4) → (5) | Reverse (3, 4); recursively solve (5) | head: 4, tail: 3 |
| 3 | (5) | Only 1 node left, cannot reverse | Return 5 as is |
| 2 returns | Connect 3 to result | 3 → 5 (already in place) | 4 → 3 → 5 |
| 1 returns | Connect 1 to result | 1 → 4 → 3 → 5 | 2 → 1 → 4 → 3 → 5 ✓ |
Pseudocode
Section titled “Pseudocode”function reverseKGroupRecursive(head, k): // Find the k-th node kth = head for i from 0 to k - 2: if not kth: return head kth = kth.next
// If no k-th node, cannot reverse this group if not kth: return head
// Save the next group's head (after k-th) nextGroupHead = kth.next
// Reverse from head to kth prev = nextGroupHead curr = head while curr != nextGroupHead: nextTemp = curr.next curr.next = prev prev = curr curr = nextTemp
// curr is now at the old head (which is now tail) // prev is at kth (which is now head) // Recursively process the rest and connect head.next = reverseKGroupRecursive(nextGroupHead, k)
return prev // Return the new head (which was kth)Solution Code
Section titled “Solution Code”from typing import Optional
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next
def reverse_k_group_recursive(head: Optional[ListNode], k: int) -> Optional[ListNode]: """ Reverse nodes in k-group recursively.
Approach: Use recursion to handle each group independently. - Check if there are k nodes remaining - Reverse the first k nodes - Recursively process the rest of the list - Connect the reversed group to the result of the recursive call
Time: O(n) - visit each node once Space: O(n/k) - recursion depth is proportional to number of groups """
def reverse_helper(node, k): """ Reverse the first k nodes starting from 'node'. Returns a tuple: (new_head, tail_of_reversed_group) """ if not node: return node, node
# Find the k-th node kth = node for i in range(k - 1): if not kth.next: # Not enough nodes, return as is return node, kth kth = kth.next
# Save the next group's head next_group_head = kth.next
# Reverse the current group (from node to kth) prev = next_group_head curr = node
while curr != next_group_head: next_temp = curr.next curr.next = prev prev = curr curr = next_temp
# curr is now at node (which will be the tail after reversal) # prev is now at kth (which will be the head after reversal) # So the head of reversed group is kth
# Recursively process the rest node.next, _ = reverse_helper(next_group_head, k)
return kth, node
result, _ = reverse_helper(head, k) return result
# Test casesdef create_linked_list(values): """Helper to create a linked list from a list of values.""" if not values: return None head = ListNode(values[0]) current = head for val in values[1:]: current.next = ListNode(val) current = current.next return head
def linked_list_to_list(head): """Helper to convert linked list to list for easy comparison.""" result = [] while head: result.append(head.val) head = head.next return result
# Testhead1 = create_linked_list([1, 2, 3, 4, 5])result1 = reverse_k_group_recursive(head1, 2)print(linked_list_to_list(result1)) # [2, 1, 4, 3, 5]
head2 = create_linked_list([1, 2, 3, 4, 5])result2 = reverse_k_group_recursive(head2, 3)print(linked_list_to_list(result2)) # [3, 2, 1, 4, 5]
head3 = create_linked_list([1])result3 = reverse_k_group_recursive(head3, 1)print(linked_list_to_list(result3)) # [1]#include <iostream>#include <vector>using namespace std;
struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {}};
ListNode* reverseKGroupRecursive(ListNode* head, int k) { /** * Reverse nodes in k-group recursively. * * Approach: Use recursion to handle each group independently. * - Check if there are k nodes remaining * - Reverse the first k nodes * - Recursively process the rest of the list * - Connect the reversed group to the result of the recursive call * * Time: O(n) - visit each node once * Space: O(n/k) - recursion depth is proportional to number of groups */
// Find the k-th node ListNode* kth = head; for (int i = 0; i < k - 1 && kth; i++) { kth = kth->next; }
// If no k-th node exists, cannot reverse, return original if (!kth) { return head; }
// Save the next group's head (after k-th node) ListNode* next_group_head = kth->next;
// Reverse from head to kth ListNode* prev = next_group_head; ListNode* curr = head;
while (curr != next_group_head) { ListNode* next_temp = curr->next; curr->next = prev; prev = curr; curr = next_temp; }
// head is now the tail of the reversed group // kth (now stored in prev) is the new head // Recursively process the remaining list and connect head->next = reverseKGroupRecursive(next_group_head, k);
return prev; // Return the new head (which was kth)}
// Helper functions for testingListNode* createList(const vector<int>& values) { if (values.empty()) return nullptr; ListNode* head = new ListNode(values[0]); ListNode* current = head; for (int i = 1; i < values.size(); i++) { current->next = new ListNode(values[i]); current = current->next; } return head;}
void printList(ListNode* head) { cout << "["; while (head) { cout << head->val; if (head->next) cout << ", "; head = head->next; } cout << "]" << endl;}
// Testint main() { ListNode* head1 = createList({1, 2, 3, 4, 5}); printList(reverseKGroupRecursive(head1, 2)); // [2, 1, 4, 3, 5]
ListNode* head2 = createList({1, 2, 3, 4, 5}); printList(reverseKGroupRecursive(head2, 3)); // [3, 2, 1, 4, 5]
ListNode* head3 = createList({1}); printList(reverseKGroupRecursive(head3, 1)); // [1]
return 0;}import java.util.*;
class ListNode { int val; ListNode next;
ListNode(int val) { this.val = val; this.next = null; }}
public class ReverseNodesInKGroupRecursive { /** * Reverse nodes in k-group recursively. * * Approach: Use recursion to handle each group independently. * - Check if there are k nodes remaining * - Reverse the first k nodes * - Recursively process the rest of the list * - Connect the reversed group to the result of the recursive call * * Time: O(n) - visit each node once * Space: O(n/k) - recursion depth is proportional to number of groups */
public static ListNode reverseKGroup(ListNode head, int k) { // Find the k-th node ListNode kth = head; for (int i = 0; i < k - 1 && kth != null; i++) { kth = kth.next; }
// If no k-th node exists, cannot reverse, return original if (kth == null) { return head; }
// Save the next group's head (after k-th node) ListNode nextGroupHead = kth.next;
// Reverse from head to kth ListNode prev = nextGroupHead; ListNode curr = head;
while (curr != nextGroupHead) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; }
// head is now the tail of the reversed group // prev is the new head (which was kth) // Recursively process the remaining list and connect head.next = reverseKGroup(nextGroupHead, k);
return prev; // Return the new head (which was kth) }
// Helper functions for testing private static ListNode createList(int[] values) { if (values.length == 0) return null; ListNode head = new ListNode(values[0]); ListNode current = head; for (int i = 1; i < values.length; i++) { current.next = new ListNode(values[i]); current = current.next; } return head; }
private static void printList(ListNode head) { System.out.print("["); while (head != null) { System.out.print(head.val); if (head.next != null) System.out.print(", "); head = head.next; } System.out.println("]"); }
// Test public static void main(String[] args) { ListNode head1 = createList(new int[]{1, 2, 3, 4, 5}); printList(reverseKGroup(head1, 2)); // [2, 1, 4, 3, 5]
ListNode head2 = createList(new int[]{1, 2, 3, 4, 5}); printList(reverseKGroup(head2, 3)); // [3, 2, 1, 4, 5]
ListNode head3 = createList(new int[]{1}); printList(reverseKGroup(head3, 1)); // [1] }}/** * Definition for singly-linked list node. */class ListNode { constructor(val = 0, next = null) { this.val = val; this.next = next; }}
/** * Reverse nodes in k-group recursively. * * Approach: Use recursion to handle each group independently. * - Check if there are k nodes remaining * - Reverse the first k nodes * - Recursively process the rest of the list * - Connect the reversed group to the result of the recursive call * * Time: O(n) - visit each node once * Space: O(n/k) - recursion depth is proportional to number of groups * * @param {ListNode} head * @param {number} k * @return {ListNode} */var reverseKGroup = function (head, k) { // Find the k-th node let kth = head; for (let i = 0; i < k - 1 && kth; i++) { kth = kth.next; }
// If no k-th node exists, cannot reverse, return original if (!kth) { return head; }
// Save the next group's head (after k-th node) const nextGroupHead = kth.next;
// Reverse from head to kth let prev = nextGroupHead; let curr = head;
while (curr !== nextGroupHead) { const nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; }
// head is now the tail of the reversed group // prev is the new head (which was kth) // Recursively process the remaining list and connect head.next = reverseKGroup(nextGroupHead, k);
return prev; // Return the new head (which was kth)};
// Helper functions for testingconst createList = (values) => { if (values.length === 0) return null; let head = new ListNode(values[0]); let current = head; for (let i = 1; i < values.length; i++) { current.next = new ListNode(values[i]); current = current.next; } return head;};
const printList = (head) => { const result = []; while (head) { result.push(head.val); head = head.next; } console.log("[" + result.join(", ") + "]");};
// Testlet head1 = createList([1, 2, 3, 4, 5]);printList(reverseKGroup(head1, 2)); // [2, 1, 4, 3, 5]
let head2 = createList([1, 2, 3, 4, 5]);printList(reverseKGroup(head2, 3)); // [3, 2, 1, 4, 5]
let head3 = createList([1]);printList(reverseKGroup(head3, 1)); // [1]use std::cell::RefCell;use std::rc::Rc;
#[derive(Debug, PartialEq, Eq)]pub struct ListNode { pub val: i32, pub next: Option<Box<ListNode>>,}
impl ListNode { #[inline] fn new(val: i32) -> Self { ListNode { next: None, val } }}
/** * Reverse nodes in k-group recursively. * * Approach: Use recursion to handle each group independently. * - Check if there are k nodes remaining * - Reverse the first k nodes * - Recursively process the rest of the list * - Connect the reversed group to the result of the recursive call * * Time: O(n) - visit each node once * Space: O(n/k) - recursion depth is proportional to number of groups */pub fn reverse_k_group(head: Option<Box<ListNode>>, k: i32) -> Option<Box<ListNode>> { // Find the k-th node let mut kth = head.as_ref(); for _ in 0..k - 1 { kth = match kth { Some(node) => node.next.as_ref(), None => return head, }; }
// If no k-th node exists, cannot reverse, return original if kth.is_none() { return head; }
// Get the node after k-th (next group's head) let mut head = head; let next_group_head = { let mut curr = head.as_mut().unwrap(); for _ in 0..k - 1 { curr = curr.next.as_mut().unwrap(); } curr.next.take() };
// Reverse the first k nodes let mut prev = next_group_head.clone(); let mut curr = head;
for _ in 0..k { let next_tmp = curr.as_mut().unwrap().next.take(); curr.as_mut().unwrap().next = prev; prev = curr; curr = next_tmp; }
// curr is now None (we've processed k nodes) // prev is the new head of the reversed group // Connect to recursive result let mut result = prev; let mut node = result.as_mut().unwrap(); for _ in 0..k - 1 { node = node.next.as_mut().unwrap(); } node.next = reverse_k_group(next_group_head, k);
result}
fn create_list(values: Vec<i32>) -> Option<Box<ListNode>> { if values.is_empty() { return None; } let mut head = Box::new(ListNode::new(values[0])); let mut current = &mut head; for i in 1..values.len() { current.next = Some(Box::new(ListNode::new(values[i]))); current = current.next.as_mut().unwrap(); } Some(head)}
fn print_list(head: Option<Box<ListNode>>) { let mut result = vec![]; let mut current = head; while let Some(node) = current { result.push(node.val.to_string()); current = node.next; } println!("[{}]", result.join(", "));}
fn main() { let head1 = create_list(vec![1, 2, 3, 4, 5]); print_list(reverse_k_group(head1, 2)); // [2, 1, 4, 3, 5]
let head2 = create_list(vec![1, 2, 3, 4, 5]); print_list(reverse_k_group(head2, 3)); // [3, 2, 1, 4, 5]
let head3 = create_list(vec![1]); print_list(reverse_k_group(head3, 1)); // [1]}package main
import "fmt"
type ListNode struct { Val int Next *ListNode}
/** * Reverse nodes in k-group recursively. * * Approach: Use recursion to handle each group independently. * - Check if there are k nodes remaining * - Reverse the first k nodes * - Recursively process the rest of the list * - Connect the reversed group to the result of the recursive call * * Time: O(n) - visit each node once * Space: O(n/k) - recursion depth is proportional to number of groups */func reverseKGroup(head *ListNode, k int) *ListNode { // Find the k-th node kth := head for i := 0; i < k-1 && kth != nil; i++ { kth = kth.Next }
// If no k-th node exists, cannot reverse, return original if kth == nil { return head }
// Save the next group's head (after k-th node) nextGroupHead := kth.Next
// Reverse from head to kth prev := nextGroupHead curr := head
for curr != nextGroupHead { nextTemp := curr.Next curr.Next = prev prev = curr curr = nextTemp }
// head is now the tail of the reversed group // prev is the new head (which was kth) // Recursively process the remaining list and connect head.Next = reverseKGroup(nextGroupHead, k)
return prev // Return the new head (which was kth)}
// Helper functions for testingfunc createList(values []int) *ListNode { if len(values) == 0 { return nil } head := &ListNode{Val: values[0]} current := head for i := 1; i < len(values); i++ { current.Next = &ListNode{Val: values[i]} current = current.Next } return head}
func printList(head *ListNode) { fmt.Print("[") first := true for head != nil { if !first { fmt.Print(", ") } fmt.Print(head.Val) first = false head = head.Next } fmt.Println("]")}
func main() { head1 := createList([]int{1, 2, 3, 4, 5}) printList(reverseKGroup(head1, 2)) // [2, 1, 4, 3, 5]
head2 := createList([]int{1, 2, 3, 4, 5}) printList(reverseKGroup(head2, 3)) // [3, 2, 1, 4, 5]
head3 := createList([]int{1}) printList(reverseKGroup(head3, 1)) // [1]}Common Pitfalls
Section titled “Common Pitfalls”Approach 3: Space-Optimized Variant
Section titled “Approach 3: Space-Optimized Variant”A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.
Pseudocode
Section titled “Pseudocode”function approach3(): // Implementation approach goes hereSolution Code
Section titled “Solution Code”"""Solution for Reverse Nodes in k-Group"""
def solve(): """Implementation for approach 3 of Reverse Nodes in k-Group""" pass
if __name__ == "__main__": print("Solution ready")#include <bits/stdc++.h>using namespace std;
// Solution for Reverse Nodes in k-Group// Approach 3: Implementation
int main() {{ // Main implementation goes here return 0;}}/** * Solution for Reverse Nodes in k-Group * Approach 3 */public class ReverseNodesInKGroupSpaceOptimized {{
public static void main(String[] args) {{ // Implementation goes here }}}}/** * Solution for Reverse Nodes in k-Group * Approach 3 */
function solve() {{ // Implementation goes here}}
module.exports = solve;/// Solution for Reverse Nodes in k-Group/// Approach 3
fn main() {{ println!("Solution implementation");}}package main
import "fmt"
// Solution for Reverse Nodes in k-Group// Approach 3
func main() {{ fmt.Println("Solution implementation")}}