Skip to content

add reverse k group linkedlist #9323

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Oct 2, 2023
Merged
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions data_structures/linked_list/reverse_k_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
from __future__ import annotations

from dataclasses import dataclass

@dataclass
class ListNode:
data: int
next_node: ListNode | None = None

def print_linked_list(head: ListNode | None) -> None:
"""
Print the entire linked list iteratively.

This function prints the elements of a linked list separated by '->'.

Parameters:
head (ListNode | None): The head of the linked list to be printed,
or None if the linked list is empty.

>>> head = insert_node(None, 0)
>>> head = insert_node(head, 2)
>>> head = insert_node(head, 1)
>>> print_linked_list(head)
0->2->1
>>> head = insert_node(head, 4)
>>> head = insert_node(head, 5)
>>> print_linked_list(head)
0->2->1->4->5
"""
if head is None:
return
while head.next_node is not None:
print(head.data, end="->")
head = head.next_node
print(head.data)

def insert_node(head: ListNode | None, data: int) -> ListNode:
"""
Insert a new node at the end of a linked list and return the new head.

Parameters:
head: The head of the linked list.
data: The data to be inserted into the new node.

Returns:
The new head of the linked list.

>>> head = insert_node(None, 10)
>>> head = insert_node(head, 9)
>>> head = insert_node(head, 8)
>>> print_linked_list(head)
10->9->8
"""
new_node = ListNode(data)
if head is None:
return new_node

temp_node = head
while temp_node.next_node:
temp_node = temp_node.next_node

temp_node.next_node = new_node
return head

class Solution:
def reverse_k_group(self, head: ListNode | None, group_size: int) -> ListNode | None:
"""
Reverse k-sized groups of nodes in a linked list.

Parameters:
head: The head of the linked list.
k: The size of each group to reverse.

Returns:
The head of the reversed linked list.

>>> head = insert_node(None, 1)
>>> head = insert_node(head, 2)
>>> head = insert_node(head, 3)
>>> head = insert_node(head, 4)
>>> head = insert_node(head, 5)
>>> head = insert_node(head, 6)
>>> solution = Solution()
>>> new_head = solution.reverse_k_group(head, 2)
>>> print_linked_list(new_head)
2->1->4->3->6->5
"""
def reverse_group(head: ListNode | None, node_size: int) -> tuple:
prev_group_tail = None
nodes_left = node_size
current_group_head = head

while current_group_head:
current_group_head = current_group_head.next_node
nodes_left -= 1

if nodes_left > 0:
return head, None, None, False

current_tail = head

while head and node_size > 0:
node_size -= 1
next_node = head.next_node
head.next_node = prev_group_tail
prev_group_tail = head
head = next_node

return prev_group_tail, current_tail, head, True

new_head, current_tail, next_group_head, success = reverse_group(head, group_size)

while success:
new_group_head, new_group_tail, next_next_group_head, success = reverse_group(next_group_head, group_size)
current_tail.next_node = new_group_head
current_tail = new_group_tail
next_group_head = next_next_group_head

return new_head

if __name__ == "__main__":
import doctest

doctest.testmod()
head = insert_node(None, 5)
head = insert_node(head, 1)
head = insert_node(head, 2)
head = insert_node(head, 4)
head = insert_node(head, 3)

print("Original list: ", end="")
print_linked_list(head)

k = 3
solution = Solution()
new_head = solution.reverse_k_group(head, k)

print(f"After reversing groups of size {k}: ", end="")
print_linked_list(new_head)