Skip to content

Commit 7ae6fbe

Browse files
committed
Optimize Ternary Search with adaptive precision and binary search fallback
- Add adaptive precision calculation based on array size - Implement binary search fallback instead of linear search (O(log n) vs O(n)) - Add optimized versions: ite_ternary_search_optimized() and rec_ternary_search_optimized() - Memoize calculations for one_third and two_third to reduce redundant computation - Add early termination conditions for better performance - Keep original functions for backward compatibility Performance improvements: - Adaptive precision: 3-10 based on array size vs fixed 10 - Binary search fallback: O(log n) vs O(n) for small ranges - Reduced redundant calculations through memoization - Better handling of edge cases and empty arrays All tests pass and maintain backward compatibility.
1 parent e2a78d4 commit 7ae6fbe

File tree

1 file changed

+177
-1
lines changed

1 file changed

+177
-1
lines changed

searches/ternary_search.py

Lines changed: 177 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,49 @@
1414
precision = 10
1515

1616

17-
# This is the linear search that will occur after the search space has become smaller.
17+
def adaptive_precision(array_size: int) -> int:
18+
"""Calculate adaptive precision based on array size.
19+
20+
Args:
21+
array_size: Size of the array
22+
23+
Returns:
24+
Optimal precision value
25+
"""
26+
if array_size <= 10:
27+
return 3
28+
elif array_size <= 100:
29+
return 5
30+
elif array_size <= 1000:
31+
return 8
32+
else:
33+
return 10
34+
35+
36+
def binary_search_fallback(left: int, right: int, array: list[int], target: int) -> int:
37+
"""Binary search fallback for small ranges (more efficient than linear search).
38+
39+
Args:
40+
left: Left boundary
41+
right: Right boundary
42+
array: Array to search in
43+
target: Target value
44+
45+
Returns:
46+
Index of target or -1 if not found
47+
"""
48+
while left <= right:
49+
mid = left + (right - left) // 2
50+
if array[mid] == target:
51+
return mid
52+
elif array[mid] < target:
53+
left = mid + 1
54+
else:
55+
right = mid - 1
56+
return -1
1857

1958

59+
# This is the linear search that will occur after the search space has become smaller.
2060
def lin_search(left: int, right: int, array: list[int], target: int) -> int:
2161
"""Perform linear search in list. Returns -1 if element is not found.
2262
@@ -109,6 +149,74 @@ def ite_ternary_search(array: list[int], target: int) -> int:
109149
return -1
110150

111151

152+
def ite_ternary_search_optimized(array: list[int], target: int) -> int:
153+
"""Optimized iterative ternary search with adaptive precision and binary search fallback.
154+
155+
Optimizations:
156+
- Adaptive precision based on array size
157+
- Binary search fallback instead of linear search
158+
- Memoized calculations for one_third and two_third
159+
- Early termination conditions
160+
161+
Args:
162+
array: Sorted array to search in
163+
target: Target value to find
164+
165+
Returns:
166+
Index of target or -1 if not found
167+
168+
Examples:
169+
>>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42]
170+
>>> ite_ternary_search_optimized(test_list, 3)
171+
-1
172+
>>> ite_ternary_search_optimized(test_list, 13)
173+
4
174+
>>> ite_ternary_search_optimized([4, 5, 6, 7], 4)
175+
0
176+
>>> ite_ternary_search_optimized([4, 5, 6, 7], -10)
177+
-1
178+
>>> ite_ternary_search_optimized([-18, 2], -18)
179+
0
180+
>>> ite_ternary_search_optimized([5], 5)
181+
0
182+
>>> ite_ternary_search_optimized([], 1)
183+
-1
184+
"""
185+
if not array:
186+
return -1
187+
188+
left = 0
189+
right = len(array) - 1
190+
adaptive_prec = adaptive_precision(len(array))
191+
192+
while left <= right:
193+
# Use binary search for small ranges (more efficient)
194+
if right - left < adaptive_prec:
195+
return binary_search_fallback(left, right, array, target)
196+
197+
# Memoize calculations
198+
range_size = right - left
199+
one_third = left + range_size // 3
200+
two_third = left + 2 * range_size // 3
201+
202+
# Early termination if found
203+
if array[one_third] == target:
204+
return one_third
205+
elif array[two_third] == target:
206+
return two_third
207+
208+
# Narrow search space
209+
if target < array[one_third]:
210+
right = one_third - 1
211+
elif array[two_third] < target:
212+
left = two_third + 1
213+
else:
214+
left = one_third + 1
215+
right = two_third - 1
216+
217+
return -1
218+
219+
112220
def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> int:
113221
"""Recursive method of the ternary search algorithm.
114222
@@ -155,6 +263,74 @@ def rec_ternary_search(left: int, right: int, array: list[int], target: int) ->
155263
return -1
156264

157265

266+
def rec_ternary_search_optimized(left: int, right: int, array: list[int], target: int) -> int:
267+
"""Optimized recursive ternary search with adaptive precision and binary search fallback.
268+
269+
Optimizations:
270+
- Adaptive precision based on array size
271+
- Binary search fallback instead of linear search
272+
- Memoized calculations for one_third and two_third
273+
- Early termination conditions
274+
275+
Args:
276+
left: Left boundary
277+
right: Right boundary
278+
array: Sorted array to search in
279+
target: Target value to find
280+
281+
Returns:
282+
Index of target or -1 if not found
283+
284+
Examples:
285+
>>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42]
286+
>>> rec_ternary_search_optimized(0, len(test_list) - 1, test_list, 3)
287+
-1
288+
>>> rec_ternary_search_optimized(4, len(test_list) - 1, test_list, 42)
289+
8
290+
>>> rec_ternary_search_optimized(0, 3, [4, 5, 6, 7], 4)
291+
0
292+
>>> rec_ternary_search_optimized(0, 3, [4, 5, 6, 7], -10)
293+
-1
294+
>>> rec_ternary_search_optimized(0, 1, [-18, 2], -18)
295+
0
296+
>>> rec_ternary_search_optimized(0, 0, [5], 5)
297+
0
298+
>>> rec_ternary_search_optimized(0, 2, ['a', 'c', 'd'], 'c')
299+
1
300+
>>> rec_ternary_search_optimized(0, 2, ['a', 'c', 'd'], 'f')
301+
-1
302+
>>> rec_ternary_search_optimized(0, -1, [], 1)
303+
-1
304+
"""
305+
if left <= right:
306+
adaptive_prec = adaptive_precision(right - left + 1)
307+
308+
# Use binary search for small ranges (more efficient)
309+
if right - left < adaptive_prec:
310+
return binary_search_fallback(left, right, array, target)
311+
312+
# Memoize calculations
313+
range_size = right - left
314+
one_third = left + range_size // 3
315+
two_third = left + 2 * range_size // 3
316+
317+
# Early termination if found
318+
if array[one_third] == target:
319+
return one_third
320+
elif array[two_third] == target:
321+
return two_third
322+
323+
# Recursively search appropriate partition
324+
if target < array[one_third]:
325+
return rec_ternary_search_optimized(left, one_third - 1, array, target)
326+
elif array[two_third] < target:
327+
return rec_ternary_search_optimized(two_third + 1, right, array, target)
328+
else:
329+
return rec_ternary_search_optimized(one_third + 1, two_third - 1, array, target)
330+
else:
331+
return -1
332+
333+
158334
if __name__ == "__main__":
159335
import doctest
160336

0 commit comments

Comments
 (0)