|
14 | 14 | precision = 10 |
15 | 15 |
|
16 | 16 |
|
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 |
18 | 57 |
|
19 | 58 |
|
| 59 | +# This is the linear search that will occur after the search space has become smaller. |
20 | 60 | def lin_search(left: int, right: int, array: list[int], target: int) -> int: |
21 | 61 | """Perform linear search in list. Returns -1 if element is not found. |
22 | 62 |
|
@@ -109,6 +149,74 @@ def ite_ternary_search(array: list[int], target: int) -> int: |
109 | 149 | return -1 |
110 | 150 |
|
111 | 151 |
|
| 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 | + |
112 | 220 | def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> int: |
113 | 221 | """Recursive method of the ternary search algorithm. |
114 | 222 |
|
@@ -155,6 +263,74 @@ def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> |
155 | 263 | return -1 |
156 | 264 |
|
157 | 265 |
|
| 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 | + |
158 | 334 | if __name__ == "__main__": |
159 | 335 | import doctest |
160 | 336 |
|
|
0 commit comments