Bueno, para empezar, supongamos que estamos usando un cuadrado.
1 2 3
2 3 4
3 4 5
1. Buscando un cuadrado
Usaría una búsqueda binaria en diagonal. El objetivo es localizar el número más pequeño que no sea estrictamente más bajo que el número objetivo.
Digamos que estoy buscando, por 4
ejemplo, luego terminaría localizando 5
en (2,2)
.
Entonces, tengo la seguridad de que si 4
está en la mesa, está en una posición (x,2)
o (2,x)
con x
adentro [0,2]
. Bueno, son solo 2 búsquedas binarias.
La complejidad no es abrumadora: O(log(N))
(3 búsquedas binarias en rangos de longitud N
)
2. Buscando un rectángulo, enfoque ingenuo
Por supuesto, se vuelve un poco más complicado cuando N
y M
difieren (con un rectángulo), considere este caso degenerado:
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17
Y digamos que estoy buscando 9
... El enfoque diagonal sigue siendo bueno, pero la definición de diagonal cambia. Aquí está mi diagonal [1, (5 or 6), 17]
. Digamos que recogí [1,5,17]
, entonces sé que si 9
está en la tabla, está en la subparte:
5 6 7 8
6 7 8 9
10 11 12 13 14 15 16
Esto nos da 2 rectángulos:
5 6 7 8 10 11 12 13 14 15 16
6 7 8 9
¡Entonces podemos recurrir! probablemente comenzando por el que tiene menos elementos (aunque en este caso nos mata).
Debo señalar que si una de las dimensiones es menor que 3
, no podemos aplicar los métodos diagonales y debemos usar una búsqueda binaria. Aquí significaría:
- Aplicar búsqueda binaria activada
10 11 12 13 14 15 16
, no encontrada
- Aplicar búsqueda binaria activada
5 6 7 8
, no encontrada
- Aplicar búsqueda binaria activada
6 7 8 9
, no encontrada
Es complicado porque para obtener un buen rendimiento, es posible que desee diferenciar entre varios casos, según la forma general ...
3. Buscando un rectángulo, enfoque brutal
Sería mucho más fácil si nos ocupamos de un cuadrado ... así que vamos a arreglar las cosas.
1 2 3 4 5 6 7 8
2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17
17 . . . . . . 17
. .
. .
. .
17 . . . . . . 17
Ahora tenemos un cuadrado.
Por supuesto, probablemente NO crearemos esas filas, simplemente podríamos emularlas.
def get(x,y):
if x < N and y < M: return table[x][y]
else: return table[N-1][M-1] # the max
por lo que se comporta como un cuadrado sin ocupar más memoria (a costa de la velocidad, probablemente, dependiendo de la caché ... bueno: p)
[[1 1][1 1]]
:?