22
33
44def binary_search (lst : list [Any ], item : Any , start : int , end : int ) -> int :
5+ """>>> binary_search([1, 3, 5], 4, 0, 2)
6+ 2
7+ >>> binary_search([1, 3, 5], 0, 0, 2)
8+ 0
9+ >>> binary_search([1, 3, 5], 6, 0, 2)
10+ 3
11+
12+ Find the insertion index for ``item`` in a sorted sublist.
13+
14+ It performs a recursive binary search on ``lst`` between indices
15+ ``start`` and ``end`` (inclusive) and returns the index showing
16+ where to insert the item so the list stays sorted.
17+
18+ Args:
19+ lst: A list of comparable items.
20+ The sublist from ``start`` to ``end`` must already be sorted.
21+ item: The value to locate an insertion index for.
22+ start: Left-most index of the sorted sublist to search.
23+ end: Right-most index of the sorted sublist to search.
24+
25+ Returns:
26+ The index at which ``item`` should be inserted.
27+
28+ Complexity:
29+ Time: ``O(log n)`` for the searched sublist.
30+ Space: ``O(log n)`` due to recursion depth.
31+ """
532 if start == end :
633 return start if lst [start ] > item else start + 1
734 if start > end :
@@ -17,6 +44,26 @@ def binary_search(lst: list[Any], item: Any, start: int, end: int) -> int:
1744
1845
1946def insertion_sort (lst : list [Any ]) -> list [Any ]:
47+ """>>> insertion_sort([3, 2, 1])
48+ [1, 2, 3]
49+
50+ Return a sorted copy of ``lst`` using insertion sort.
51+
52+ Uses ``binary_search`` to find where to insert each item. The
53+ input list is not modified; a new sorted list is returned.
54+
55+ Args:
56+ lst: The list to sort. A new list is returned; the input list is
57+ not modified in-place.
58+
59+ Returns:
60+ A new list containing the elements of ``lst`` in ascending order.
61+
62+ Complexity:
63+ Time: ``O(n^2)`` in the worst case because each insertion may
64+ shift many elements.
65+ Space: ``O(n)`` for the reconstructed list copies.
66+ """
2067 length = len (lst )
2168
2269 for index in range (1 , length ):
@@ -28,6 +75,23 @@ def insertion_sort(lst: list[Any]) -> list[Any]:
2875
2976
3077def merge (left : list [Any ], right : list [Any ]) -> list [Any ]:
78+ """>>> merge([1, 4], [2, 3])
79+ [1, 2, 3, 4]
80+
81+ Merge two sorted lists and return a new sorted list.
82+
83+ Args:
84+ left: A list sorted in ascending order.
85+ right: A list sorted in ascending order.
86+
87+ Returns:
88+ A new list containing all elements from ``left`` and ``right`` in
89+ ascending order.
90+
91+ Complexity:
92+ Time: ``O(n + m)`` where ``n`` and ``m`` are the input lengths.
93+ Space: ``O(n + m)`` because recursive slicing creates new lists.
94+ """
3195 if not left :
3296 return right
3397
@@ -42,6 +106,15 @@ def merge(left: list[Any], right: list[Any]) -> list[Any]:
42106
43107def tim_sort (lst : list [Any ] | tuple [Any , ...] | str ) -> list [Any ]:
44108 """
109+ Sort and return the input using a TimSort-like approach: detect
110+ runs, sort each run with insertion sort, then merge the runs.
111+
112+ Complexity:
113+ Time: ``O(n log n)`` in the common case.
114+ Space: ``O(n)`` for the extra lists used during sorting.
115+
116+ >>> tim_sort([])
117+ []
45118 >>> tim_sort("Python")
46119 ['P', 'h', 'n', 'o', 't', 'y']
47120 >>> tim_sort((1.1, 1, 0, -1, -1.1))
@@ -52,8 +125,7 @@ def tim_sort(lst: list[Any] | tuple[Any, ...] | str) -> list[Any]:
52125 True
53126 >>> tim_sort([3, 2, 1]) == sorted([3, 2, 1])
54127 True
55- >>> tim_sort([])
56- []
128+
57129 """
58130 if not lst :
59131 return []
0 commit comments