Skip to content
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

add reverse k group linkedlist #9323

Merged
merged 17 commits into from
Oct 2, 2023
Merged
Changes from all 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
118 changes: 118 additions & 0 deletions data_structures/linked_list/reverse_k_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from __future__ import annotations

from collections.abc import Iterable, Iterator
from dataclasses import dataclass


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


class LinkedList:
def __init__(self, ints: Iterable[int]) -> None:
self.head: Node | None = None
for i in ints:
self.append(i)

def __iter__(self) -> Iterator[int]:
"""
>>> ints = []
>>> list(LinkedList(ints)) == ints
True
>>> ints = tuple(range(5))
>>> tuple(LinkedList(ints)) == ints
True
"""
node = self.head
while node:
yield node.data
node = node.next_node

def __len__(self) -> int:
"""
>>> for i in range(3):
... len(LinkedList(range(i))) == i
True
True
True
>>> len(LinkedList("abcdefgh"))
8
"""
return sum(1 for _ in self)

def __str__(self) -> str:
"""
>>> str(LinkedList([]))
''
>>> str(LinkedList(range(5)))
'0 -> 1 -> 2 -> 3 -> 4'
"""
return " -> ".join([str(node) for node in self])

def append(self, data: int) -> None:
"""
>>> ll = LinkedList([1, 2])
>>> tuple(ll)
(1, 2)
>>> ll.append(3)
>>> tuple(ll)
(1, 2, 3)
>>> ll.append(4)
>>> tuple(ll)
(1, 2, 3, 4)
>>> len(ll)
4
"""
if not self.head:
self.head = Node(data)
return
node = self.head
while node.next_node:
node = node.next_node
node.next_node = Node(data)

def reverse_k_nodes(self, group_size: int) -> None:
"""
reverse nodes within groups of size k
>>> ll = LinkedList([1, 2, 3, 4, 5])
>>> ll.reverse_k_nodes(2)
>>> tuple(ll)
(2, 1, 4, 3, 5)
>>> str(ll)
'2 -> 1 -> 4 -> 3 -> 5'
"""
if self.head is None or self.head.next_node is None:
return

length = len(self)
dummy_head = Node(0)
dummy_head.next_node = self.head
previous_node = dummy_head

while length >= group_size:
current_node = previous_node.next_node
assert current_node
next_node = current_node.next_node
for _ in range(1, group_size):
assert next_node, current_node
current_node.next_node = next_node.next_node
assert previous_node
next_node.next_node = previous_node.next_node
previous_node.next_node = next_node
next_node = current_node.next_node
previous_node = current_node
length -= group_size
self.head = dummy_head.next_node


if __name__ == "__main__":
import doctest

doctest.testmod()
ll = LinkedList([1, 2, 3, 4, 5])
print(f"Original Linked List: {ll}")
k = 2
ll.reverse_k_nodes(k)
print(f"After reversing groups of size {k}: {ll}")