From ccb5f65d79e84744692c4aec3f446319c3ced528 Mon Sep 17 00:00:00 2001 From: BamaCharanChhandogi Date: Sun, 1 Oct 2023 23:40:59 +0530 Subject: [PATCH 01/17] add reverse k group linkedlist --- .../linked_list/reverse_k_group.py | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 data_structures/linked_list/reverse_k_group.py diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py new file mode 100644 index 000000000000..e4e2b9dee8c2 --- /dev/null +++ b/data_structures/linked_list/reverse_k_group.py @@ -0,0 +1,106 @@ +from typing import Optional + +class ListNode: + def __init__(self, val=0): + self.val = val + self.next = None + +class Solution: + def reverse(self, head: Optional[ListNode], k: int) -> tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + """ + Reverse the next k nodes in a linked list. + + Args: + head (Optional[ListNode]): The head of the linked list. + k (int): The number of nodes to reverse. + + Returns: + tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + - The new head of the reversed group. + - The tail of the reversed group. + - The new head after the reversed group. + - A boolean indicating if there are more nodes to reverse. + + Example: + >>> sol = Solution() + >>> head = ListNode(1) + >>> head.next = ListNode(2) + >>> head.next.next = ListNode(3) + >>> head.next.next.next = ListNode(4) + >>> head.next.next.next.next = ListNode(5) + >>> reversed_head, tail, new_head, found = sol.reverse(head, 2) + >>> reversed_head.val + 2 + >>> tail.val + 1 + >>> new_head.val + 3 + >>> found + True + """ + prev_group_end = None + remaining_count = k + current_group_start = head + + # Calculate the remaining nodes in the list + while current_group_start: + current_group_start = current_group_start.next + remaining_count -= 1 + + # If there are less than k nodes remaining, return the original head + if remaining_count > 0: + return head, None, None, False + + current_group_end = head + while head and k > 0: + k -= 1 + next_node = head.next + head.next = prev_group_end + prev_group_end = head + head = next_node + + return prev_group_end, current_group_end, head, True + + def reverse_k_group(self, head: Optional[ListNode], k: int) -> Optional[ListNode]: + """ + Reverse nodes in a linked list in groups of k. + + Args: + head (Optional[ListNode]): The head of the linked list. + k (int): The number of nodes in each group to reverse. + + Returns: + Optional[ListNode]: The new head of the reversed linked list. + + Example: + >>> sol = Solution() + >>> head = ListNode(1) + >>> head.next = ListNode(2) + >>> head.next.next = ListNode(3) + >>> head.next.next.next = ListNode(4) + >>> head.next.next.next.next = ListNode(5) + >>> new_head = sol.reverse_k_group(head, 2) + >>> new_head.val + 2 + >>> new_head.next.val + 1 + >>> new_head.next.next.val + 4 + >>> new_head.next.next.next.val + 3 + >>> new_head.next.next.next.next.val + 5 + """ + reversed_head, tail, new_head, found = self.reverse(head, k) + + while found: + group_head, group_tail, new_head, found = self.reverse(new_head, k) + tail.next = group_head + tail = group_tail + + return reversed_head + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 4e7dc87b865e770ef99621904370fd0176ac73a5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 18:13:44 +0000 Subject: [PATCH 02/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/linked_list/reverse_k_group.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index e4e2b9dee8c2..392d20fc05c9 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -1,12 +1,16 @@ from typing import Optional + class ListNode: def __init__(self, val=0): self.val = val self.next = None + class Solution: - def reverse(self, head: Optional[ListNode], k: int) -> tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + def reverse( + self, head: Optional[ListNode], k: int + ) -> tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: """ Reverse the next k nodes in a linked list. @@ -15,7 +19,7 @@ def reverse(self, head: Optional[ListNode], k: int) -> tuple[Optional[ListNode], k (int): The number of nodes to reverse. Returns: - tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: - The new head of the reversed group. - The tail of the reversed group. - The new head after the reversed group. @@ -100,7 +104,8 @@ def reverse_k_group(self, head: Optional[ListNode], k: int) -> Optional[ListNode return reversed_head + if __name__ == "__main__": import doctest - + doctest.testmod() From 3bfffd46113ea081122ff2aab22b6dafd1be0968 Mon Sep 17 00:00:00 2001 From: BamaCharanChhandogi Date: Mon, 2 Oct 2023 00:02:27 +0530 Subject: [PATCH 03/17] update --- .../linked_list/reverse_k_group.py | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 392d20fc05c9..87ea8587f973 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -1,25 +1,21 @@ from typing import Optional - class ListNode: - def __init__(self, val=0): + def __init__(self, val: int = 0) -> None: self.val = val self.next = None - class Solution: - def reverse( - self, head: Optional[ListNode], k: int - ) -> tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + def reverse(self, head: Optional[ListNode], node_size: int) -> tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: """ - Reverse the next k nodes in a linked list. + Reverse the next k(node_size) nodes in a linked list. Args: head (Optional[ListNode]): The head of the linked list. - k (int): The number of nodes to reverse. + node_size (int): The number of nodes to reverse. Returns: - tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: - The new head of the reversed group. - The tail of the reversed group. - The new head after the reversed group. @@ -43,7 +39,7 @@ def reverse( True """ prev_group_end = None - remaining_count = k + remaining_count = node_size current_group_start = head # Calculate the remaining nodes in the list @@ -56,8 +52,8 @@ def reverse( return head, None, None, False current_group_end = head - while head and k > 0: - k -= 1 + while head and node_size > 0: + node_size -= 1 next_node = head.next head.next = prev_group_end prev_group_end = head @@ -65,13 +61,13 @@ def reverse( return prev_group_end, current_group_end, head, True - def reverse_k_group(self, head: Optional[ListNode], k: int) -> Optional[ListNode]: + def reverse_k_group(self, head: Optional[ListNode], group_size: int) -> Optional[ListNode]: """ - Reverse nodes in a linked list in groups of k. + Reverse nodes in a linked list in groups of k(group_size). Args: head (Optional[ListNode]): The head of the linked list. - k (int): The number of nodes in each group to reverse. + group_size (int): The number of nodes in each group to reverse. Returns: Optional[ListNode]: The new head of the reversed linked list. @@ -95,17 +91,16 @@ def reverse_k_group(self, head: Optional[ListNode], k: int) -> Optional[ListNode >>> new_head.next.next.next.next.val 5 """ - reversed_head, tail, new_head, found = self.reverse(head, k) + reversed_head, tail, new_head, found = self.reverse(head, group_size) while found: - group_head, group_tail, new_head, found = self.reverse(new_head, k) + group_head, group_tail, new_head, found = self.reverse(new_head, group_size) tail.next = group_head tail = group_tail return reversed_head - if __name__ == "__main__": import doctest - + doctest.testmod() From 3cb7a18565d95bdc80b62381a7d5e4dc35cdf029 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 18:33:03 +0000 Subject: [PATCH 04/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/linked_list/reverse_k_group.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 87ea8587f973..cc5d95988b71 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -1,12 +1,16 @@ from typing import Optional + class ListNode: def __init__(self, val: int = 0) -> None: self.val = val self.next = None + class Solution: - def reverse(self, head: Optional[ListNode], node_size: int) -> tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + def reverse( + self, head: Optional[ListNode], node_size: int + ) -> tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: """ Reverse the next k(node_size) nodes in a linked list. @@ -15,7 +19,7 @@ def reverse(self, head: Optional[ListNode], node_size: int) -> tuple[Optional[Li node_size (int): The number of nodes to reverse. Returns: - tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: - The new head of the reversed group. - The tail of the reversed group. - The new head after the reversed group. @@ -61,7 +65,9 @@ def reverse(self, head: Optional[ListNode], node_size: int) -> tuple[Optional[Li return prev_group_end, current_group_end, head, True - def reverse_k_group(self, head: Optional[ListNode], group_size: int) -> Optional[ListNode]: + def reverse_k_group( + self, head: Optional[ListNode], group_size: int + ) -> Optional[ListNode]: """ Reverse nodes in a linked list in groups of k(group_size). @@ -100,7 +106,8 @@ def reverse_k_group(self, head: Optional[ListNode], group_size: int) -> Optional return reversed_head + if __name__ == "__main__": import doctest - + doctest.testmod() From 2fa29749a8f04c96f67ea0429831e69b5ca0505e Mon Sep 17 00:00:00 2001 From: BamaCharanChhandogi Date: Mon, 2 Oct 2023 00:17:21 +0530 Subject: [PATCH 05/17] update --- .../linked_list/reverse_k_group.py | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index cc5d95988b71..6ca3a7524d6d 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -1,16 +1,15 @@ -from typing import Optional - +from typing import Optional, Union, Tuple class ListNode: def __init__(self, val: int = 0) -> None: self.val = val self.next = None - class Solution: - def reverse( - self, head: Optional[ListNode], node_size: int - ) -> tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + def reverse(self, head: Optional[ListNode], node_size: int) -> Union[ + Tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool], + Tuple[Optional[ListNode], None, None, bool] + ]: """ Reverse the next k(node_size) nodes in a linked list. @@ -19,7 +18,7 @@ def reverse( node_size (int): The number of nodes to reverse. Returns: - tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: - The new head of the reversed group. - The tail of the reversed group. - The new head after the reversed group. @@ -65,9 +64,8 @@ def reverse( return prev_group_end, current_group_end, head, True - def reverse_k_group( - self, head: Optional[ListNode], group_size: int - ) -> Optional[ListNode]: + def reverse_k_group(self, head: Optional[ListNode], group_size: int) -> Optional[ListNode]: + """ Reverse nodes in a linked list in groups of k(group_size). @@ -106,8 +104,7 @@ def reverse_k_group( return reversed_head - if __name__ == "__main__": import doctest - + doctest.testmod() From b2ce90dfab0c0d4c99000cfe942c1f385a95a4d0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 18:48:16 +0000 Subject: [PATCH 06/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/linked_list/reverse_k_group.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 6ca3a7524d6d..027152cfc08f 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -1,14 +1,18 @@ from typing import Optional, Union, Tuple + class ListNode: def __init__(self, val: int = 0) -> None: self.val = val self.next = None + class Solution: - def reverse(self, head: Optional[ListNode], node_size: int) -> Union[ + def reverse( + self, head: Optional[ListNode], node_size: int + ) -> Union[ Tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool], - Tuple[Optional[ListNode], None, None, bool] + Tuple[Optional[ListNode], None, None, bool], ]: """ Reverse the next k(node_size) nodes in a linked list. @@ -18,7 +22,7 @@ def reverse(self, head: Optional[ListNode], node_size: int) -> Union[ node_size (int): The number of nodes to reverse. Returns: - tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: + tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: - The new head of the reversed group. - The tail of the reversed group. - The new head after the reversed group. @@ -64,8 +68,9 @@ def reverse(self, head: Optional[ListNode], node_size: int) -> Union[ return prev_group_end, current_group_end, head, True - def reverse_k_group(self, head: Optional[ListNode], group_size: int) -> Optional[ListNode]: - + def reverse_k_group( + self, head: Optional[ListNode], group_size: int + ) -> Optional[ListNode]: """ Reverse nodes in a linked list in groups of k(group_size). @@ -104,7 +109,8 @@ def reverse_k_group(self, head: Optional[ListNode], group_size: int) -> Optional return reversed_head + if __name__ == "__main__": import doctest - + doctest.testmod() From 04394345d3911bf9da320209c283cbeaf5dd8ac4 Mon Sep 17 00:00:00 2001 From: BamaCharanChhandogi Date: Mon, 2 Oct 2023 01:10:20 +0530 Subject: [PATCH 07/17] update --- .../linked_list/reverse_k_group.py | 215 ++++++++++-------- 1 file changed, 119 insertions(+), 96 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 027152cfc08f..839e00aa8ab7 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -1,116 +1,139 @@ -from typing import Optional, Union, Tuple +from __future__ import annotations +from dataclasses import dataclass +@dataclass class ListNode: - def __init__(self, val: int = 0) -> None: - self.val = val - self.next = None - + 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( - self, head: Optional[ListNode], node_size: int - ) -> Union[ - Tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool], - Tuple[Optional[ListNode], None, None, bool], - ]: + def reverse_k_group(self, head: ListNode | None, k: int) -> ListNode | None: """ - Reverse the next k(node_size) nodes in a linked list. + Reverse k-sized groups of nodes in a linked list. - Args: - head (Optional[ListNode]): The head of the linked list. - node_size (int): The number of nodes to reverse. + Parameters: + head: The head of the linked list. + k: The size of each group to reverse. Returns: - tuple[Optional[ListNode], Optional[ListNode], Optional[ListNode], bool]: - - The new head of the reversed group. - - The tail of the reversed group. - - The new head after the reversed group. - - A boolean indicating if there are more nodes to reverse. - - Example: - >>> sol = Solution() - >>> head = ListNode(1) - >>> head.next = ListNode(2) - >>> head.next.next = ListNode(3) - >>> head.next.next.next = ListNode(4) - >>> head.next.next.next.next = ListNode(5) - >>> reversed_head, tail, new_head, found = sol.reverse(head, 2) - >>> reversed_head.val - 2 - >>> tail.val - 1 - >>> new_head.val - 3 - >>> found - True - """ - prev_group_end = None - remaining_count = node_size - current_group_start = head - - # Calculate the remaining nodes in the list - while current_group_start: - current_group_start = current_group_start.next - remaining_count -= 1 - - # If there are less than k nodes remaining, return the original head - if remaining_count > 0: - return head, None, None, False - - current_group_end = head - while head and node_size > 0: - node_size -= 1 - next_node = head.next - head.next = prev_group_end - prev_group_end = head - head = next_node - - return prev_group_end, current_group_end, head, True - - def reverse_k_group( - self, head: Optional[ListNode], group_size: int - ) -> Optional[ListNode]: + 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 """ - Reverse nodes in a linked list in groups of k(group_size). + def reverse_group(head: ListNode | None, k: int) -> tuple: + prev_group_tail = None + nodes_left = k + current_group_head = head - Args: - head (Optional[ListNode]): The head of the linked list. - group_size (int): The number of nodes in each group to reverse. + while current_group_head: + current_group_head = current_group_head.next_node + nodes_left -= 1 - Returns: - Optional[ListNode]: The new head of the reversed linked list. - - Example: - >>> sol = Solution() - >>> head = ListNode(1) - >>> head.next = ListNode(2) - >>> head.next.next = ListNode(3) - >>> head.next.next.next = ListNode(4) - >>> head.next.next.next.next = ListNode(5) - >>> new_head = sol.reverse_k_group(head, 2) - >>> new_head.val - 2 - >>> new_head.next.val - 1 - >>> new_head.next.next.val - 4 - >>> new_head.next.next.next.val - 3 - >>> new_head.next.next.next.next.val - 5 - """ - reversed_head, tail, new_head, found = self.reverse(head, group_size) + if nodes_left > 0: + return head, None, None, False + + current_tail = head - while found: - group_head, group_tail, new_head, found = self.reverse(new_head, group_size) - tail.next = group_head - tail = group_tail + while head and k > 0: + k -= 1 + next_node = head.next_node + head.next_node = prev_group_tail + prev_group_tail = head + head = next_node - return reversed_head + return prev_group_tail, current_tail, head, True + new_head, current_tail, next_group_head, success = reverse_group(head, k) + + while success: + new_group_head, new_group_tail, next_next_group_head, success = reverse_group(next_group_head, k) + 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) From d1673c1dc666f047518899fe4bc51680d4e1caa3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:41:13 +0000 Subject: [PATCH 08/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/linked_list/reverse_k_group.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 839e00aa8ab7..6c4ae2226aa2 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -2,11 +2,13 @@ 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. @@ -34,6 +36,7 @@ def print_linked_list(head: ListNode | None) -> None: 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. @@ -62,6 +65,7 @@ def insert_node(head: ListNode | None, data: int) -> ListNode: temp_node.next_node = new_node return head + class Solution: def reverse_k_group(self, head: ListNode | None, k: int) -> ListNode | None: """ @@ -85,6 +89,7 @@ def reverse_k_group(self, head: ListNode | None, k: int) -> ListNode | None: >>> print_linked_list(new_head) 2->1->4->3->6->5 """ + def reverse_group(head: ListNode | None, k: int) -> tuple: prev_group_tail = None nodes_left = k @@ -111,13 +116,19 @@ def reverse_group(head: ListNode | None, k: int) -> tuple: new_head, current_tail, next_group_head, success = reverse_group(head, k) while success: - new_group_head, new_group_tail, next_next_group_head, success = reverse_group(next_group_head, k) + ( + new_group_head, + new_group_tail, + next_next_group_head, + success, + ) = reverse_group(next_group_head, k) 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 From 4605137ff7477c10ecee4e24b62b8e6a0d3c40ae Mon Sep 17 00:00:00 2001 From: BamaCharanChhandogi Date: Mon, 2 Oct 2023 01:20:16 +0530 Subject: [PATCH 09/17] update --- .../linked_list/reverse_k_group.py | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 6c4ae2226aa2..6d845b2abd63 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -2,13 +2,11 @@ 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. @@ -36,7 +34,6 @@ def print_linked_list(head: ListNode | None) -> None: 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. @@ -65,9 +62,8 @@ def insert_node(head: ListNode | None, data: int) -> ListNode: temp_node.next_node = new_node return head - class Solution: - def reverse_k_group(self, head: ListNode | None, k: int) -> ListNode | None: + def reverse_k_group(self, head: ListNode | None, group_size: int) -> ListNode | None: """ Reverse k-sized groups of nodes in a linked list. @@ -89,10 +85,9 @@ def reverse_k_group(self, head: ListNode | None, k: int) -> ListNode | None: >>> print_linked_list(new_head) 2->1->4->3->6->5 """ - - def reverse_group(head: ListNode | None, k: int) -> tuple: + def reverse_group(head: ListNode | None, node_size: int) -> tuple: prev_group_tail = None - nodes_left = k + nodes_left = node_size current_group_head = head while current_group_head: @@ -104,8 +99,8 @@ def reverse_group(head: ListNode | None, k: int) -> tuple: current_tail = head - while head and k > 0: - k -= 1 + while head and node_size > 0: + node_size -= 1 next_node = head.next_node head.next_node = prev_group_tail prev_group_tail = head @@ -113,22 +108,16 @@ def reverse_group(head: ListNode | None, k: int) -> tuple: return prev_group_tail, current_tail, head, True - new_head, current_tail, next_group_head, success = reverse_group(head, k) + 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, k) + 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 From 3b45f3cf4e9ccd3a3b03e984f5c55a7653d75be7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:50:52 +0000 Subject: [PATCH 10/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../linked_list/reverse_k_group.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 6d845b2abd63..c00aa6ff90ee 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -2,11 +2,13 @@ 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. @@ -34,6 +36,7 @@ def print_linked_list(head: ListNode | None) -> None: 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. @@ -62,8 +65,11 @@ def insert_node(head: ListNode | None, data: int) -> ListNode: temp_node.next_node = new_node return head + class Solution: - def reverse_k_group(self, head: ListNode | None, group_size: int) -> ListNode | None: + def reverse_k_group( + self, head: ListNode | None, group_size: int + ) -> ListNode | None: """ Reverse k-sized groups of nodes in a linked list. @@ -85,6 +91,7 @@ def reverse_k_group(self, head: ListNode | None, group_size: int) -> ListNode | >>> 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 @@ -108,16 +115,24 @@ def reverse_group(head: ListNode | None, node_size: int) -> tuple: return prev_group_tail, current_tail, head, True - new_head, current_tail, next_group_head, success = reverse_group(head, group_size) + 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) + ( + 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 From ffd8d631f382f7c77e44b3355b6943f63510cb1c Mon Sep 17 00:00:00 2001 From: BamaCharanChhandogi Date: Mon, 2 Oct 2023 01:35:14 +0530 Subject: [PATCH 11/17] update --- .../linked_list/reverse_k_group.py | 202 ++++++++---------- 1 file changed, 86 insertions(+), 116 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index c00aa6ff90ee..7d0ba6b39189 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -4,151 +4,121 @@ @dataclass -class ListNode: +class Node: data: int - next_node: ListNode | None = None + next_node: Node | None = None -def print_linked_list(head: ListNode | None) -> None: +def insert_node(head: Node | None, data: int) -> Node: """ - 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) + Insert a new node at the end of a linked list and return the new head. + >>> head = insert_node(None, 1) >>> 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) + >>> head = insert_node(head, 3) >>> print_linked_list(head) - 0->2->1->4->5 + 1->2->3 """ + new_node = Node(data) + # If the linked list is empty, the new_node becomes the head if head is None: - return - while head.next_node is not None: - print(head.data, end="->") - head = head.next_node - print(head.data) - + return new_node -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. + temp_node = head + while temp_node.next_node is not None: + temp_node = temp_node.next_node - Parameters: - head: The head of the linked list. - data: The data to be inserted into the new node. + temp_node.next_node = new_node # type: ignore + return head - Returns: - The new head of the linked list. +def length_of_linked_list(head: Node | None) -> int: + """ + find length of linked list >>> head = insert_node(None, 10) >>> head = insert_node(head, 9) >>> head = insert_node(head, 8) - >>> print_linked_list(head) - 10->9->8 + >>> length_of_linked_list(head) + 3 """ - new_node = ListNode(data) - if head is None: - return new_node + length = 0 + while head is not None: + length += 1 + head = head.next_node + return length - temp_node = head - while temp_node.next_node: - temp_node = temp_node.next_node - temp_node.next_node = new_node - return head +def print_linked_list(head: Node | None) -> None: + """ + print the entire linked list + >>> head = insert_node(None, 1) + >>> head = insert_node(head, 2) + >>> head = insert_node(head, 3) + >>> print_linked_list(head) + 1->2->3 + """ + if head is not None: + while head.next_node is not None: + print(head.data, end="->") + head = head.next_node + print(head.data) -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 +def reverse_k_nodes(head: Node | None, group_size: int) -> Node | None: + """ + reverse nodes within groups of size k + >>> 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) + >>> new_head = reverse_k_nodes(head, 2) + >>> print_linked_list(new_head) + 2->1->4->3->5 + """ + if head is None or head.next_node is None: + return head + + length = length_of_linked_list(head) + + dummy_head = Node(0) + dummy_head.next_node = head + + previous_node = dummy_head + + while length >= group_size: + assert previous_node + 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 + assert previous_node + previous_node.next_node = next_node + assert current_node + next_node = current_node.next_node + previous_node = current_node + length -= group_size + assert dummy_head + return dummy_head.next_node if __name__ == "__main__": import doctest doctest.testmod() - head = insert_node(None, 5) - head = insert_node(head, 1) + + k = 2 + head = insert_node(None, 1) head = insert_node(head, 2) - head = insert_node(head, 4) head = insert_node(head, 3) + head = insert_node(head, 4) + head = insert_node(head, 5) - print("Original list: ", end="") + print("Original Linked 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="") + new_head = reverse_k_nodes(head, k) print_linked_list(new_head) From 54721627b939873094420947b9e50e37c5593b4b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 2 Oct 2023 02:00:23 +0200 Subject: [PATCH 12/17] Update reverse_k_group.py --- .../linked_list/reverse_k_group.py | 209 +++++++++--------- 1 file changed, 104 insertions(+), 105 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 7d0ba6b39189..c407e721498d 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -9,116 +9,115 @@ class Node: next_node: Node | None = None -def insert_node(head: Node | None, data: int) -> Node: - """ - Insert a new node at the end of a linked list and return the new head. - >>> head = insert_node(None, 1) - >>> head = insert_node(head, 2) - >>> head = insert_node(head, 3) - >>> print_linked_list(head) - 1->2->3 - """ - new_node = Node(data) - # If the linked list is empty, the new_node becomes the head - if head is None: - return new_node - - temp_node = head - while temp_node.next_node is not None: - temp_node = temp_node.next_node - - temp_node.next_node = new_node # type: ignore - return head - - -def length_of_linked_list(head: Node | None) -> int: - """ - find length of linked list - >>> head = insert_node(None, 10) - >>> head = insert_node(head, 9) - >>> head = insert_node(head, 8) - >>> length_of_linked_list(head) - 3 - """ - length = 0 - while head is not None: - length += 1 - head = head.next_node - return length - - -def print_linked_list(head: Node | None) -> None: - """ - print the entire linked list - >>> head = insert_node(None, 1) - >>> head = insert_node(head, 2) - >>> head = insert_node(head, 3) - >>> print_linked_list(head) - 1->2->3 - """ - if head is not None: - while head.next_node is not None: - print(head.data, end="->") - head = head.next_node - print(head.data) - - -def reverse_k_nodes(head: Node | None, group_size: int) -> Node | None: - """ - reverse nodes within groups of size k - >>> 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) - >>> new_head = reverse_k_nodes(head, 2) - >>> print_linked_list(new_head) - 2->1->4->3->5 - """ - if head is None or head.next_node is None: - return head - - length = length_of_linked_list(head) - - dummy_head = Node(0) - dummy_head.next_node = head - - previous_node = dummy_head - - while length >= group_size: - assert previous_node - 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 - assert previous_node - previous_node.next_node = next_node - assert current_node +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: + # assert previous_node + current_node = previous_node.next_node + # assert current_node next_node = current_node.next_node - previous_node = current_node - length -= group_size - assert dummy_head - return dummy_head.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 + # assert previous_node + previous_node.next_node = next_node + # assert current_node + next_node = current_node.next_node + previous_node = current_node + length -= group_size + # assert dummy_head + 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 - 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) - - print("Original Linked List: ", end="") - print_linked_list(head) - print(f"After reversing groups of size {k}: ", end="") - new_head = reverse_k_nodes(head, k) - print_linked_list(new_head) + ll.reverse_k_nodes(k) + print(f"After reversing groups of size {k}: {ll}") From 9553239642675d047af1b858a14661d54076e4a9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 00:00:57 +0000 Subject: [PATCH 13/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/linked_list/reverse_k_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index c407e721498d..0820041385bc 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -49,7 +49,7 @@ def __str__(self) -> str: '0 -> 1 -> 2 -> 3 -> 4' """ return " -> ".join([str(node) for node in self]) - + def append(self, data: int) -> None: """ >>> ll = LinkedList([1, 2]) From 79200f902b668a1f7122cd27bbe830098d290802 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 2 Oct 2023 02:06:45 +0200 Subject: [PATCH 14/17] Update reverse_k_group.py --- data_structures/linked_list/reverse_k_group.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 0820041385bc..bac3ba92f9df 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -1,5 +1,6 @@ from __future__ import annotations +from collections.abc import Iterable, Iterator from dataclasses import dataclass @@ -49,7 +50,7 @@ def __str__(self) -> str: '0 -> 1 -> 2 -> 3 -> 4' """ return " -> ".join([str(node) for node in self]) - + def append(self, data: int) -> None: """ >>> ll = LinkedList([1, 2]) @@ -95,12 +96,12 @@ def reverse_k_nodes(self, group_size: int) -> None: while length >= group_size: # assert previous_node current_node = previous_node.next_node - # assert current_node + assert current_node next_node = current_node.next_node for _ in range(1, group_size): - # assert next_node, current_node + assert next_node, current_node current_node.next_node = next_node.next_node - # assert previous_node + assert previous_node next_node.next_node = previous_node.next_node # assert previous_node previous_node.next_node = next_node @@ -116,6 +117,7 @@ def reverse_k_nodes(self, group_size: int) -> None: import doctest doctest.testmod() + ll = LinkedList([1, 2, 3, 4, 5]) print(f"Original Linked List: {ll}") k = 2 From 0f9ad1d1240e351b5792a168a76447a40aa411d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 00:07:17 +0000 Subject: [PATCH 15/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/linked_list/reverse_k_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index bac3ba92f9df..90b0b070c428 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -50,7 +50,7 @@ def __str__(self) -> str: '0 -> 1 -> 2 -> 3 -> 4' """ return " -> ".join([str(node) for node in self]) - + def append(self, data: int) -> None: """ >>> ll = LinkedList([1, 2]) From 24804c83a554328705a4238dd6ec47b6f14fcfc9 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 2 Oct 2023 02:12:47 +0200 Subject: [PATCH 16/17] Update reverse_k_group.py --- data_structures/linked_list/reverse_k_group.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 90b0b070c428..83142bf8e53f 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -50,7 +50,7 @@ def __str__(self) -> str: '0 -> 1 -> 2 -> 3 -> 4' """ return " -> ".join([str(node) for node in self]) - + def append(self, data: int) -> None: """ >>> ll = LinkedList([1, 2]) @@ -87,14 +87,11 @@ def reverse_k_nodes(self, group_size: int) -> None: return length = len(self) - dummy_head = Node(0) dummy_head.next_node = self.head - previous_node = dummy_head while length >= group_size: - # assert previous_node current_node = previous_node.next_node assert current_node next_node = current_node.next_node @@ -103,13 +100,10 @@ def reverse_k_nodes(self, group_size: int) -> None: current_node.next_node = next_node.next_node assert previous_node next_node.next_node = previous_node.next_node - # assert previous_node previous_node.next_node = next_node - # assert current_node next_node = current_node.next_node previous_node = current_node length -= group_size - # assert dummy_head self.head = dummy_head.next_node @@ -117,7 +111,6 @@ def reverse_k_nodes(self, group_size: int) -> None: import doctest doctest.testmod() - ll = LinkedList([1, 2, 3, 4, 5]) print(f"Original Linked List: {ll}") k = 2 From 538e2c19a30a4491418113225ab1e0712c62a489 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 00:13:21 +0000 Subject: [PATCH 17/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/linked_list/reverse_k_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_structures/linked_list/reverse_k_group.py b/data_structures/linked_list/reverse_k_group.py index 83142bf8e53f..5fc45491a540 100644 --- a/data_structures/linked_list/reverse_k_group.py +++ b/data_structures/linked_list/reverse_k_group.py @@ -50,7 +50,7 @@ def __str__(self) -> str: '0 -> 1 -> 2 -> 3 -> 4' """ return " -> ".join([str(node) for node in self]) - + def append(self, data: int) -> None: """ >>> ll = LinkedList([1, 2])