|
| 1 | +""" |
| 2 | +Este código implementa duas versões de busca exponencial em arrays ordenados, |
| 3 | +uma usando acesso direto ao array e outra simulando o ArrayReader do LeetCode 702. |
1 | 4 |
|
2 | | -def binary_search(nums, n, low, high): |
3 | | - while low < high: |
4 | | - mid = int((low + high)/2) |
| 5 | +Objetivo: |
| 6 | +- A classe Solution implementa a busca exponencial diretamente em um array normal. |
| 7 | +- A classe Solution1 implementa a busca exponencial em um array de tamanho desconhecido |
| 8 | + usando a interface ArrayReader, combinando exponential search com binary search. |
| 9 | +- A classe ArrayReader simula a interface usada no LeetCode, retornando um valor |
| 10 | + muito grande caso o índice acessado esteja fora do limite. |
| 11 | +""" |
5 | 12 |
|
6 | | - if nums[mid] == n: |
7 | | - return mid |
8 | | - elif nums[mid] < n: |
9 | | - low = mid+1 |
10 | | - else: |
11 | | - high = mid |
12 | | - return -1 |
| 13 | +# Simula o ArrayReader do LeetCode |
| 14 | +class ArrayReader: |
| 15 | + def __init__(self, arr): |
| 16 | + # Armazena o array interno |
| 17 | + self.arr = arr |
13 | 18 |
|
| 19 | + def get(self, index: int) -> int: |
| 20 | + # Se o índice está dentro do array, retorna o valor correspondente |
| 21 | + if 0 <= index < len(self.arr): |
| 22 | + return self.arr[index] |
| 23 | + # Caso contrário, retorna um valor muito grande (simulando índice fora do array) |
| 24 | + return 2**31 -1 |
14 | 25 |
|
15 | | -def exponencial_search(arr, target): |
16 | | - if arr[0] == target: |
17 | | - return 0 |
18 | | - n = len(arr) |
19 | | - i = 1 |
20 | 26 |
|
21 | | - while i < n and arr[i] < target: |
22 | | - i *= 2 |
| 27 | +# Implementação de Exponential Search com acesso direto ao array |
| 28 | +class Solution(): |
| 29 | + @staticmethod |
| 30 | + def binary_search(nums, n, low, high): |
| 31 | + """ |
| 32 | + Busca binária em um array ordenado entre os índices low e high. |
| 33 | + Retorna o índice do elemento n ou -1 se não encontrado. |
| 34 | + """ |
| 35 | + while low < high: |
| 36 | + # Calcula o índice do meio do intervalo |
| 37 | + mid = int((low + high)/2) |
23 | 38 |
|
24 | | - if arr[i] == target: |
25 | | - return i |
| 39 | + if nums[mid] == n: |
| 40 | + # Encontrou o elemento |
| 41 | + return mid |
| 42 | + elif nums[mid] < n: |
| 43 | + # Elemento está à direita |
| 44 | + low = mid + 1 |
| 45 | + else: |
| 46 | + # Elemento está à esquerda |
| 47 | + high = mid |
| 48 | + # Não encontrou o elemento |
| 49 | + return -1 |
26 | 50 |
|
27 | | - return binary_search(arr, target, i//2, min(i, n-1)) |
| 51 | + def exponencial_search(self, arr, target): |
| 52 | + """ |
| 53 | + Busca exponencial em um array ordenado. |
| 54 | + Primeiro encontra um intervalo em que o target pode estar, |
| 55 | + depois aplica busca binária nesse intervalo. |
| 56 | + """ |
| 57 | + # Caso o primeiro elemento seja o target |
| 58 | + if arr[0] == target: |
| 59 | + return 0 |
| 60 | + n = len(arr) |
| 61 | + i = 1 |
28 | 62 |
|
| 63 | + # Dobrar o índice até ultrapassar o target ou o tamanho do array |
| 64 | + while i < n and arr[i] < target: |
| 65 | + i *= 2 |
29 | 66 |
|
30 | | -d = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40] |
31 | | -target = 14 |
32 | | -result = exponencial_search(d, target) |
| 67 | + # Caso o elemento esteja exatamente no índice encontrado |
| 68 | + if arr[i] == target: |
| 69 | + return i |
33 | 70 |
|
34 | | -print(f"Element found at index {result}") |
| 71 | + # Aplicar busca binária no intervalo encontrado |
| 72 | + return Solution.binary_search(arr, target, i//2, min(i, n-1)) |
| 73 | + |
| 74 | + |
| 75 | +# Implementação de Exponential Search usando ArrayReader (tamanho desconhecido) |
| 76 | +class Solution1(): |
| 77 | + def search(self, reader: ArrayReader, target: int) -> int: |
| 78 | + # Caso base: verifica o primeiro elemento |
| 79 | + if reader.get(0) == target: |
| 80 | + return 0 |
| 81 | + |
| 82 | + # 1) Busca exponencial para encontrar o intervalo |
| 83 | + i = 1 |
| 84 | + while reader.get(i) < target: |
| 85 | + # Dobrar o índice até encontrar valor >= target |
| 86 | + i *= 2 |
| 87 | + |
| 88 | + # 2) Busca binária dentro do intervalo [i//2, i] |
| 89 | + low, high = i // 2, i |
| 90 | + while low <= high: |
| 91 | + # Índice do meio do intervalo |
| 92 | + mid = (low + high) // 2 |
| 93 | + # Valor no índice mid |
| 94 | + val = reader.get(mid) |
| 95 | + |
| 96 | + if val == target: |
| 97 | + # Encontrou o target |
| 98 | + return mid |
| 99 | + elif val > target: |
| 100 | + # Target está à esquerda |
| 101 | + high = mid - 1 |
| 102 | + else: |
| 103 | + # Target está à direita |
| 104 | + low = mid + 1 |
| 105 | + |
| 106 | + # Target não encontrado |
| 107 | + return -1 |
0 commit comments