From 5fe8aeb1ce1009604728e33a3dae59d070d8d063 Mon Sep 17 00:00:00 2001 From: Sai Rahul Guggilam Date: Fri, 24 Oct 2025 11:17:31 +0100 Subject: [PATCH 1/5] merge variety --- sorts/3_way_Merge_Sort.py | 79 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 sorts/3_way_Merge_Sort.py diff --git a/sorts/3_way_Merge_Sort.py b/sorts/3_way_Merge_Sort.py new file mode 100644 index 000000000000..cc1d691f5acc --- /dev/null +++ b/sorts/3_way_Merge_Sort.py @@ -0,0 +1,79 @@ +''' +In traditional Merge Sort, the array is recursively divided into halves until we reach subarrays of size 1. In 3-way Merge Sort, the array is recursively divided into three parts, reducing the depth of recursion and potentially improving efficiency. +''' +def merge(arr, left, mid1, mid2, right): + + # Sizes of three subarrays + size1 = mid1 - left + 1 + size2 = mid2 - mid1 + size3 = right - mid2 + + # Temporary arrays for three parts + left_arr = arr[left:left + size1] + mid_arr = arr[mid1 + 1:mid1 + 1 + size2] + right_arr = arr[mid2 + 1:mid2 + 1 + size3] + + # Merge three sorted subarrays + i = j = k = 0 + index = left + + while i < size1 or j < size2 or k < size3: + min_value = float('inf') + min_idx = -1 + + # Find the smallest among the three current elements + if i < size1 and left_arr[i] < min_value: + min_value = left_arr[i] + min_idx = 0 + if j < size2 and mid_arr[j] < min_value: + min_value = mid_arr[j] + min_idx = 1 + if k < size3 and right_arr[k] < min_value: + min_value = right_arr[k] + min_idx = 2 + + # Place the smallest element in the merged array + if min_idx == 0: + arr[index] = left_arr[i] + i += 1 + elif min_idx == 1: + arr[index] = mid_arr[j] + j += 1 + else: + arr[index] = right_arr[k] + k += 1 + + index += 1 + +def three_way_merge_sort(arr, left, right): + + # Base case: If single element, return + if left >= right: + return + + # Finding two midpoints for 3-way split + mid1 = left + (right - left) // 3 + mid2 = left + 2 * (right - left) // 3 + + # Recursively sort first third + three_way_merge_sort(arr, left, mid1) + + # Recursively sort second third + three_way_merge_sort(arr, mid1 + 1, mid2) + + # Recursively sort last third + three_way_merge_sort(arr, mid2 + 1, right) + + # Merge the sorted parts + merge(arr, left, mid1, mid2, right) + +if __name__ == "__main__": + + # Input array + arr = [5, 2, 9, 1, 6, 3, 8, 4, 7] + + # Calling 3-way merge sort function + three_way_merge_sort(arr, 0, len(arr) - 1) + + # Printing the sorted array + print(*arr) \ No newline at end of file From 21e9b86a94d590522c2674f78e14640be5efdb2c Mon Sep 17 00:00:00 2001 From: Sai Rahul Guggilam Date: Fri, 24 Oct 2025 11:24:18 +0100 Subject: [PATCH 2/5] merge variety --- sorts/{3_way_Merge_Sort.py => three_way_merge_sort.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sorts/{3_way_Merge_Sort.py => three_way_merge_sort.py} (100%) diff --git a/sorts/3_way_Merge_Sort.py b/sorts/three_way_merge_sort.py similarity index 100% rename from sorts/3_way_Merge_Sort.py rename to sorts/three_way_merge_sort.py From 97a8891b22604efae8c3d21197497cdc8875f50b Mon Sep 17 00:00:00 2001 From: Sai Rahul Guggilam Date: Fri, 24 Oct 2025 17:23:23 +0100 Subject: [PATCH 3/5] Sleep sort --- sorts/sleep_sort.py | 83 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 sorts/sleep_sort.py diff --git a/sorts/sleep_sort.py b/sorts/sleep_sort.py new file mode 100644 index 000000000000..698d6fd1f916 --- /dev/null +++ b/sorts/sleep_sort.py @@ -0,0 +1,83 @@ +""" +An implementation of Sleep Sort. + +Description +----------- +Sleep Sort is a highly unconventional algorithm that leverages timing delays +to produce a sorted sequence. Each element in the array is assigned to a thread +that sleeps for a duration proportional to its value. As threads "wake up," +they output numbers in increasing order. + +This algorithm only works for non-negative integers and is non-deterministic +in real systems due to thread scheduling and timing inaccuracies. + +Time complexity: O(n) expected (but unreliable in practice) +Space complexity: O(n) for thread management +""" + +import threading +import time +from typing import List + + +def sleep_sort(arr: List[int]) -> List[int]: + """ + Sorts a list of non-negative integers using the Sleep Sort algorithm. + + Parameters + ---------- + arr : List[int] + A list of non-negative integers to be sorted. + + Returns + ------- + List[int] + A new list containing the elements in sorted order. + + Example + ------- + >>> sleep_sort([3, 1, 2]) + [1, 2, 3] + """ + if not arr: + return [] + + result: List[int] = [] + threads = [] + + def _sleep_and_append(n: int) -> None: + """Sleeps for n * 0.01 seconds and appends n to the result.""" + time.sleep(n * 0.01) + result.append(n) + + for num in arr: + if num < 0: + raise ValueError("Sleep Sort only supports non-negative integers.") + thread = threading.Thread(target=_sleep_and_append, args=(num,)) + threads.append(thread) + thread.start() + + for thread in threads: + thread.join() + + return result + + +def _test() -> None: + """Basic test cases for sleep_sort.""" + test_cases = [ + [], + [1], + [3, 1, 2], + [0, 0, 1], + [5, 3, 9, 1, 4], + ] + + for case in test_cases: + sorted_case = sorted(case) + assert sleep_sort(case) == sorted_case, f"Failed on {case}" + print("All tests passed.") + + +if __name__ == "__main__": + _test() From a962b6e8e452ff8878d787fc417a8d04039c38b4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:27:50 +0000 Subject: [PATCH 4/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- sorts/three_way_merge_sort.py | 47 ++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/sorts/three_way_merge_sort.py b/sorts/three_way_merge_sort.py index cc1d691f5acc..adc51e5cf51d 100644 --- a/sorts/three_way_merge_sort.py +++ b/sorts/three_way_merge_sort.py @@ -1,26 +1,27 @@ -''' +""" In traditional Merge Sort, the array is recursively divided into halves until we reach subarrays of size 1. In 3-way Merge Sort, the array is recursively divided into three parts, reducing the depth of recursion and potentially improving efficiency. -''' +""" + + def merge(arr, left, mid1, mid2, right): - # Sizes of three subarrays size1 = mid1 - left + 1 size2 = mid2 - mid1 size3 = right - mid2 - + # Temporary arrays for three parts - left_arr = arr[left:left + size1] - mid_arr = arr[mid1 + 1:mid1 + 1 + size2] - right_arr = arr[mid2 + 1:mid2 + 1 + size3] - + left_arr = arr[left : left + size1] + mid_arr = arr[mid1 + 1 : mid1 + 1 + size2] + right_arr = arr[mid2 + 1 : mid2 + 1 + size3] + # Merge three sorted subarrays i = j = k = 0 index = left - + while i < size1 or j < size2 or k < size3: - min_value = float('inf') + min_value = float("inf") min_idx = -1 - + # Find the smallest among the three current elements if i < size1 and left_arr[i] < min_value: min_value = left_arr[i] @@ -31,7 +32,7 @@ def merge(arr, left, mid1, mid2, right): if k < size3 and right_arr[k] < min_value: min_value = right_arr[k] min_idx = 2 - + # Place the smallest element in the merged array if min_idx == 0: arr[index] = left_arr[i] @@ -42,38 +43,38 @@ def merge(arr, left, mid1, mid2, right): else: arr[index] = right_arr[k] k += 1 - + index += 1 + def three_way_merge_sort(arr, left, right): - # Base case: If single element, return if left >= right: return - + # Finding two midpoints for 3-way split mid1 = left + (right - left) // 3 mid2 = left + 2 * (right - left) // 3 - + # Recursively sort first third three_way_merge_sort(arr, left, mid1) - + # Recursively sort second third three_way_merge_sort(arr, mid1 + 1, mid2) - + # Recursively sort last third three_way_merge_sort(arr, mid2 + 1, right) - + # Merge the sorted parts merge(arr, left, mid1, mid2, right) + if __name__ == "__main__": - # Input array arr = [5, 2, 9, 1, 6, 3, 8, 4, 7] - + # Calling 3-way merge sort function three_way_merge_sort(arr, 0, len(arr) - 1) - + # Printing the sorted array - print(*arr) \ No newline at end of file + print(*arr) From 106eb15b0691806d784279b1eb48d7e14ae6fb64 Mon Sep 17 00:00:00 2001 From: Sai Rahul Guggilam Date: Tue, 28 Oct 2025 11:29:48 +0000 Subject: [PATCH 5/5] Flatten_binary_tree --- .../linked_list/flatten_binary_tree.py | 102 ++++++++++++++++++ knapsack/test_flatten_binary_tree.py | 0 2 files changed, 102 insertions(+) create mode 100644 data_structures/linked_list/flatten_binary_tree.py create mode 100644 knapsack/test_flatten_binary_tree.py diff --git a/data_structures/linked_list/flatten_binary_tree.py b/data_structures/linked_list/flatten_binary_tree.py new file mode 100644 index 000000000000..493bae61a727 --- /dev/null +++ b/data_structures/linked_list/flatten_binary_tree.py @@ -0,0 +1,102 @@ +""" +Flatten a binary tree to a linked list in-place. + +The algorithm modifies the given binary tree so that it becomes a right-skewed +linked list following preorder traversal order (root -> left -> right). + +Time complexity: O(n) +Space complexity: O(1) (excluding recursion stack) + +Doctest: +>>> # build tree: [1,2,5,3,4,None,6] +>>> root = TreeNode(1, TreeNode(2, TreeNode(3), TreeNode(4)), TreeNode(5, None, TreeNode(6))) +>>> flatten(root) +>>> to_list(root) +[1, 2, 3, 4, 5, 6] + +>>> # single node +>>> root = TreeNode(0) +>>> flatten(root) +>>> to_list(root) +[0] +""" + +from __future__ import annotations +from typing import Optional, List +import doctest + + +class TreeNode: + """ + Node of a binary tree. + + Attributes: + val (int): Node value. + left (Optional[TreeNode]): Left child. + right (Optional[TreeNode]): Right child. + """ + + def __init__( + self, + val: int = 0, + left: Optional["TreeNode"] = None, + right: Optional["TreeNode"] = None, + ) -> None: + self.val = val + self.left = left + self.right = right + + +def flatten(root: Optional[TreeNode]) -> None: + """ + Flatten the binary tree rooted at `root` into a right-skewed linked list + following preorder traversal. Modifies the tree in-place. + + Args: + root (Optional[TreeNode]]): Root of the binary tree. + + Returns: + None + """ + current = root + while current: + if current.left: + # Find rightmost node of left subtree (predecessor) + predecessor = current.left + while predecessor.right: + predecessor = predecessor.right + + # Move current.right after predecessor + predecessor.right = current.right + # Make left subtree the new right subtree + current.right = current.left + current.left = None + current = current.right + + +def to_list(root: Optional[TreeNode]) -> List[int]: + """ + Helper to collect values from the flattened tree following right pointers. + + Args: + root (Optional[TreeNode]): Root of the (flattened) tree. + + Returns: + List[int]: Values in order along right pointers. + """ + result: List[int] = [] + node = root + while node: + result.append(node.val) + node = node.right + return result + + +if __name__ == "__main__": + # Run doctests when executed as a script. + # This is intended for local checks only. Formal tests should go in tests/. + failures, tests = doctest.testmod(report=False) + if failures: + print(f"Doctest failures: {failures} out of {tests} tests.") + else: + print(f"All {tests} doctests passed.") diff --git a/knapsack/test_flatten_binary_tree.py b/knapsack/test_flatten_binary_tree.py new file mode 100644 index 000000000000..e69de29bb2d1