Búsqueda binaria
Encuentra un valor en un array ordenado mirando el elemento del centro y descartando la mitad que no puede contenerlo: un millón de datos en solo 20 comparaciones.
Visualízalo paso a paso
Cambia los datos, dale a reproducir y sigue cada paso en el dibujo, en la línea de Java que se ejecuta y en sus variables.
Búsqueda binaria
Escribe un array ordenado (hasta 16 números) y el valor que buscas.
- en la zona de trabajo
Paso 1
Buscamos el 23 entre 10 números ordenados. Al principio puede estar en cualquier sitio: la zona va de izq = 0 a der = 9.
1static int buscar(int[] a, int x) {
2 int izq = 0, der = a.length - 1; // x = 23, izq = 0, der = 9
3 while (izq <= der) {
4 int medio = izq + (der - izq) / 2;
5 if (a[medio] == x) return medio;
6 if (a[medio] < x) izq = medio + 1;
7 else der = medio - 1;
8 }
9 return -1;
10}Variables
- x
- 23
- izq
- 0
- der
- 9
- comparaciones
- 0
Atajos con el foco dentro del visualizador: ← → paso a paso, Espacio reproducir o pausar, Inicio/Fin ir al principio o al final.
La idea
Para buscar una palabra en un diccionario nadie empieza por la primera página: se abre por la mitad, se mira si la palabra va antes o después y se descarta la otra mitad. Se repite con la mitad que queda hasta encontrarla o quedarse sin páginas.
La búsqueda binaria hace exactamente eso con un array ordenado: compara el valor buscado con el elemento central; si es igual, lo ha encontrado; si es menor, sigue por la mitad izquierda; si es mayor, por la derecha. Cada comparación descarta la mitad de lo que queda, así que con n elementos hacen falta como mucho ⌊log₂ n⌋ + 1 comparaciones.
La condición imprescindible es que los datos estén ordenados, y por el mismo criterio con el que se compara. Sobre un array desordenado no da ningún error: da respuestas equivocadas.
La misma idea sirve para mucho más que buscar un valor: para encontrar la primera posición que cumple una condición (la primera nota aprobada en una lista ordenada) o para encontrar el valor mínimo que hace posible algo, probando por la mitad del rango de respuestas posibles (la búsqueda binaria sobre la respuesta).
Cuándo usarlo
- Los datos están ordenados y se puede ir directo a cualquier posición (arrays,
ArrayList). - Hay que buscar muchas veces en los mismos datos: ordenarlos una vez (O(n log n)) y buscar después en O(log n) compensa enseguida.
- Hay que encontrar una frontera: la primera posición con un valor mayor o igual que x, el primer día en que se supera un umbral, la primera versión que falla.
- Hay que encontrar el mínimo (o máximo) valor que cumple una condición que, una vez se cumple, se cumple para todos los valores mayores.
Cuándo no
- Los datos están desordenados y solo se va a buscar una vez: ordenar cuesta más que mirar todos (búsqueda lineal, O(n)).
- En listas enlazadas (
LinkedList): llegar al centro cuesta recorrer media lista. - Si los datos cambian todo el rato: mantener el array ordenado al insertar cuesta O(n); es mejor un
TreeSeto, si no hace falta el orden, unHashSet.
Paso a paso
- Delimitar la zona. Dos índices,
izq = 0yder = n - 1, marcan la zona del array donde todavía puede estar el valor. - Mirar el centro. Mientras la zona no esté vacía (
izq <= der), se calculamedio = izq + (der - izq) / 2y se comparaa[medio]con el valor buscado. - Descartar la mitad. Si
a[medio]es el valor, se ha encontrado. Si es menor, el valor solo puede estar a la derecha:izq = medio + 1. Si es mayor, a la izquierda:der = medio - 1. - Zona vacía. Si
izqsupera ader, no está. En ese momentoizqes justo la posición donde habría que insertarlo para mantener el orden.
El código
Búsqueda binaria iterativa
La versión que se usa en la práctica: un bucle, dos índices y memoria constante.
1public class Main {
2 /** Posición de x en el array ordenado a, o -1 si no está. */
3 static int buscar(int[] a, int x) {
4 int izq = 0, der = a.length - 1; // x solo puede estar en a[izq..der]
5 while (izq <= der) {
6 int medio = izq + (der - izq) / 2; // así la suma no se desborda
7 if (a[medio] == x) return medio;
8 if (a[medio] < x) izq = medio + 1; // x está a la derecha del medio
9 else der = medio - 1; // x está a la izquierda
10 }
11 return -1; // la zona se ha quedado vacía
12 }
13
14 public static void main(String[] args) {
15 int[] a = {3, 8, 15, 23, 42, 57, 61, 78, 90};
16 System.out.println("buscar(a, 57) = " + buscar(a, 57));
17 System.out.println("buscar(a, 4) = " + buscar(a, 4) + " (no está)");
18 }
19}def buscar(a, x):
"""Posición de x en la lista ordenada a, o -1 si no está."""
izq, der = 0, len(a) - 1 # x solo puede estar en a[izq..der]
while izq <= der:
medio = (izq + der) // 2 # en Python los enteros no se desbordan
if a[medio] == x:
return medio
if a[medio] < x:
izq = medio + 1 # x está a la derecha del medio
else:
der = medio - 1 # x está a la izquierda
return -1 # la zona se ha quedado vacía
a = [3, 8, 15, 23, 42, 57, 61, 78, 90]
print("buscar(a, 57) =", buscar(a, 57))
print("buscar(a, 4) =", buscar(a, 4), "(no está)")/** Posición de x en el array ordenado a, o -1 si no está. */
function buscar(a, x) {
let izq = 0, der = a.length - 1; // x solo puede estar en a[izq..der]
while (izq <= der) {
const medio = Math.floor((izq + der) / 2); // la división entera hay que hacerla a mano
if (a[medio] === x) return medio;
if (a[medio] < x) izq = medio + 1; // x está a la derecha del medio
else der = medio - 1; // x está a la izquierda
}
return -1; // la zona se ha quedado vacía
}
const a = [3, 8, 15, 23, 42, 57, 61, 78, 90];
console.log(`buscar(a, 57) = ${buscar(a, 57)}`);
console.log(`buscar(a, 4) = ${buscar(a, 4)} (no está)`);using System;
class Program {
// Posición de x en el array ordenado a, o -1 si no está.
static int Buscar(int[] a, int x) {
int izq = 0, der = a.Length - 1; // x solo puede estar en a[izq..der]
while (izq <= der) {
int medio = izq + (der - izq) / 2; // así la suma no se desborda
if (a[medio] == x) return medio;
if (a[medio] < x) izq = medio + 1; // x está a la derecha del medio
else der = medio - 1; // x está a la izquierda
}
return -1; // la zona se ha quedado vacía
}
static void Main() {
int[] a = { 3, 8, 15, 23, 42, 57, 61, 78, 90 };
Console.WriteLine(quot;buscar(a, 57) = {Buscar(a, 57)}");
Console.WriteLine(quot;buscar(a, 4) = {Buscar(a, 4)} (no está)");
}
}<?php
/** Posición de $x en el array ordenado $a, o -1 si no está. */
function buscar(array $a, int $x): int {
$izq = 0;
$der = count($a) - 1; // $x solo puede estar en $a[$izq..$der]
while ($izq <= $der) {
$medio = intdiv($izq + $der, 2); // división entera
if ($a[$medio] === $x) return $medio;
if ($a[$medio] < $x) $izq = $medio + 1; // $x está a la derecha del medio
else $der = $medio - 1; // $x está a la izquierda
}
return -1; // la zona se ha quedado vacía
}
$a = [3, 8, 15, 23, 42, 57, 61, 78, 90];
echo "buscar(a, 57) = " . buscar($a, 57) . "\n";
echo "buscar(a, 4) = " . buscar($a, 4) . " (no está)\n";Salida al ejecutarlo (la misma en los 5 lenguajes)
buscar(a, 57) = 5 buscar(a, 4) = -1 (no está)
Versión recursiva
La misma idea escrita con recursividad: más cercana a la definición, pero gasta un marco de la pila por cada llamada.
1/** La misma búsqueda, recursiva: cada llamada mira una zona la mitad de grande. */
2static int buscar(int[] a, int x, int izq, int der) {
3 if (izq > der) return -1; // caso base: zona vacía
4 int medio = izq + (der - izq) / 2;
5 if (a[medio] == x) return medio;
6 return a[medio] < x ? buscar(a, x, medio + 1, der)
7 : buscar(a, x, izq, medio - 1);
8}def buscar(a, x, izq, der):
"""La misma búsqueda, recursiva: cada llamada mira una zona la mitad de grande."""
if izq > der: # caso base: zona vacía
return -1
medio = (izq + der) // 2
if a[medio] == x:
return medio
if a[medio] < x:
return buscar(a, x, medio + 1, der)
return buscar(a, x, izq, medio - 1)/** La misma búsqueda, recursiva: cada llamada mira una zona la mitad de grande. */
function buscar(a, x, izq = 0, der = a.length - 1) {
if (izq > der) return -1; // caso base: zona vacía
const medio = Math.floor((izq + der) / 2);
if (a[medio] === x) return medio;
return a[medio] < x ? buscar(a, x, medio + 1, der)
: buscar(a, x, izq, medio - 1);
}// La misma búsqueda, recursiva: cada llamada mira una zona la mitad de grande.
static int Buscar(int[] a, int x, int izq, int der) {
if (izq > der) return -1; // caso base: zona vac ía
int medio = izq + (der - izq) / 2;
if (a[medio] == x) return medio;
return a[medio] < x ? Buscar(a, x, medio + 1, der)
: Buscar(a, x, izq, medio - 1);
}/** La misma búsqueda, recursiva: cada llamada mira una zona la mitad de grande. */
function buscar(array $a, int $x, int $izq, int $der): int {
if ($izq > $der) return -1; // caso base: zona vacía
$medio = intdiv($izq + $der, 2);
if ($a[$medio] === $x) return $medio;
return $a[$medio] < $x ? buscar($a, $x, $medio + 1, $der)
: buscar($a, $x, $izq, $medio - 1);
}Con valores repetidos: la primera posición mayor o igual
La búsqueda clásica devuelve cualquiera de las apariciones de un valor repetido. Para encontrar la primera se busca la frontera: la primera posición cuyo valor es mayor o igual que x. Es lo que en C++ se llama lower_bound.
1/** Primera posición con a[i] >= x (a.length si no hay ninguna): sirve con valores repetidos. */
2static int primeraMayorOIgual(int[] a, int x) {
3 int izq = 0, der = a.length; // ojo: aquí der es exclusivo, la zona es a[izq..der)
4 while (izq < der) {
5 int medio = izq + (der - izq) / 2;
6 if (a[medio] < x) izq = medio + 1;
7 else der = medio; // a[medio] >= x: el medio puede ser la respuesta
8 }
9 return izq; // izq == der: la frontera
10}def primera_mayor_o_igual(a, x):
"""Primera posición con a[i] >= x (len(a) si no hay ninguna): sirve con valores repetidos."""
izq, der = 0, len(a) # ojo: aquí der es exclusivo, la zona es a[izq..der)
while izq < der:
medio = (izq + der) // 2
if a[medio] < x:
izq = medio + 1
else:
der = medio # a[medio] >= x: el medio puede ser la respuesta
return izq # izq == der: la frontera
# La biblioteca estándar ya la trae: bisect.bisect_left(a, x) hace exactamente esto/** Primera posición con a[i] >= x (a.length si no hay ninguna): sirve con valores repetidos. */
function primeraMayorOIgual(a, x) {
let izq = 0, der = a.length; // ojo: aquí der es exclusivo, la zona es a[izq..der)
while (izq < der) {
const medio = Math.floor((izq + der) / 2);
if (a[medio] < x) izq = medio + 1;
else der = medio; // a[medio] >= x: el medio puede ser la respuesta
}
return izq; // izq == der: la frontera
}// Primera posición con a[i] >= x (a.Length si no hay ninguna): sirve con valores repetidos.
static int PrimeraMayorOIgual(int[] a, int x) {
int izq = 0, der = a.Length; // ojo: aquí der es exclusivo, la zona es a[izq..der)
while (izq < der) {
int medio = izq + (der - izq) / 2;
if (a[medio] < x) izq = medio + 1;
else der = medio; // a[medio] >= x: el medio puede ser la respuesta
}
return izq; // izq == der: la frontera
}
// Array.BinarySearch(a, x) devuelve la posición o, si no está, ~(dónde iría): con repetidos
// puede devolver cualquiera de ellos, por eso esta versión./** Primera posición con $a[$i] >= $x (count($a) si no hay ninguna): sirve con valores repetidos. */
function primeraMayorOIgual(array $a, int $x): int {
$izq = 0;
$der = count($a); // ojo: aquí $der es exclusivo, la zona es $a[$izq..$der)
while ($izq < $der) {
$medio = intdiv($izq + $der, 2);
if ($a[$medio] < $x) $izq = $medio + 1;
else $der = $medio; // $a[$medio] >= $x: el medio puede ser la respuesta
}
return $izq; // $izq == $der: la frontera
}Traza: buscar 23 en {3, 8, 15, 23, 42, 57, 61, 78, 90}
| Paso | izq | der | medio | a[medio] | Decisión |
|---|---|---|---|---|---|
| 1 | 0 | 8 | 4 | 42 | 23 < 42 → der = 3 |
| 2 | 0 | 3 | 1 | 8 | 23 > 8 → izq = 2 |
| 3 | 2 | 3 | 2 | 15 | 23 > 15 → izq = 3 |
| 4 | 3 | 3 | 3 | 23 | encontrado en la posición 3 |
Cuatro comparaciones para nueve elementos; una búsqueda lineal habría necesitado otras cuatro para llegar al 23, pero para el 90 habría necesitado nueve y la binaria, cuatro.
Complejidad
| Datos (n) | Búsqueda lineal (peor caso) | Búsqueda binaria (peor caso) |
|---|---|---|
| 1.000 | 1.000 comparaciones | 10 comparaciones |
| 1.000.000 | 1.000.000 | 20 |
| 1.000.000.000 | 1.000.000.000 | 30 |
La búsqueda binaria es O(log n): duplicar los datos solo añade una comparación. El mejor caso es O(1) (el valor está justo en el centro). En memoria, la versión iterativa es O(1) y la recursiva O(log n), por las llamadas que se apilan.
- Mejor caso: O(1)
- Caso medio: O(log n)
- Peor caso: O(log n)
Duplicar los datos solo añade una comparación. Las curvas grises son las demás clases, para comparar.
En la práctica
Arrays.binarySearch(a, x)yCollections.binarySearch(lista, x): si el valor no está devuelven-(punto de inserción) - 1, un número negativo que dice dónde iría.- Los índices de las bases de datos (árboles B+) bajan por niveles descartando ramas, la misma idea con muchos hijos por nodo.
git bisectencuentra el commit que introdujo un error con una búsqueda binaria entre un commit bueno y uno malo.- Muchos problemas de optimización («la capacidad mínima», «el tiempo mínimo») se resuelven con búsqueda binaria sobre la respuesta.
Errores típicos
- Calcular el medio con
(izq + der) / 2: con índices enormes la suma se desborda y sale negativa.izq + (der - izq) / 2no se desborda (este fallo estuvo años en la propia biblioteca de Java). - Mezclar las dos convenciones: con
derinclusivo el bucle eswhile (izq <= der)y se actualiza conmedio ± 1; conderexclusivo eswhile (izq < der)yder = medio. Mezclarlas deja un elemento sin mirar o un bucle infinito. - Actualizar con
izq = medioen la versión inclusiva: cuandoizqyderquedan juntos, el medio no cambia y el bucle no termina. - Usarla sobre datos sin ordenar, u ordenados con otro criterio (por ejemplo, nombres ordenados sin tener en cuenta mayúsculas y buscados con
compareTo). - Esperar la primera aparición de un valor repetido: la versión clásica devuelve una cualquiera.
Ejercicios
Cada ejercicio se corrige solo con sus pruebas (algunas ocultas). Escribe tu solución en el editor y pulsa Ejecutar o Comprobar; la solución explicada está debajo, por si te atascas.
1. Primera y última aparición
La primera línea trae un array de enteros ordenado de menor a mayor (puede tener repetidos). Cada línea siguiente es una consulta: un número. Para cada consulta, di cuántas veces aparece y entre qué posiciones, usando dos búsquedas binarias: la primera posición con un valor mayor o igual y la primera con un valor mayor. El main ya está escrito: completa las dos funciones.
- Si aparece:
x aparece N veces, de la posición I a la J(ox aparece 1 vez, en la posición I). - Si no aparece:
x no está; iría en la posición P(donde habría que insertarlo para que siga ordenado). - Una consulta que no es un número:
Consulta no válida: «texto». Si el array no está ordenado:El array no está ordenadoy nada más.
Ejemplo
1 3 3 3 5 8 8 13 3 8 4 13 0 20
3 aparece 3 veces, de la posición 1 a la 3 8 aparece 2 veces, de la posición 5 a la 6 4 no está; iría en la posición 4 13 aparece 1 vez, en la posición 7 0 no está; iría en la posición 0 20 no está; iría en la posición 8
Ver la solución explicada
1import java.util.*;
2
3public class Main {
4 /** Primera posición con a[i] >= x (a.length si no hay ninguna). */
5 static int primeraMayorOIgual(int[] a, int x) {
6 int izq = 0, der = a.length;
7 while (izq < der) {
8 int medio = izq + (der - izq) / 2;
9 if (a[medio] < x) izq = medio + 1;
10 else der = medio;
11 }
12 return izq;
13 }
14
15 /** Primera posición con a[i] > x (a.length si no hay ninguna). */
16 static int primeraMayor(int[] a, int x) {
17 int izq = 0, der = a.length;
18 while (izq < der) {
19 int medio = izq + (der - izq) / 2;
20 if (a[medio] <= x) izq = medio + 1;
21 else der = medio;
22 }
23 return izq;
24 }
25
26 public static void main(String[] args) {
27 Scanner sc = new Scanner(System.in);
28 String primera = sc.hasNextLine() ? sc.nextLine().trim() : "";
29 int[] a;
30 try {
31 a = primera.isEmpty() ? new int[0] : Arrays.stream(primera.split("\\s+")).mapToInt(Integer::parseInt).toArray();
32 } catch (NumberFormatException e) {
33 System.out.println("Array no válido");
34 return;
35 }
36 for (int i = 1; i < a.length; i++) {
37 if (a[i] < a[i - 1]) {
38 System.out.println("El array no está ordenado");
39 return;
40 }
41 }
42 while (sc.hasNextLine()) {
43 String linea = sc.nextLine().trim();
44 if (linea.isEmpty()) continue;
45 int x;
46 try {
47 x = Integer.parseInt(linea);
48 } catch (NumberFormatException e) {
49 System.out.println("Consulta no válida: «" + linea + "»");
50 continue;
51 }
52 int desde = primeraMayorOIgual(a, x), hasta = primeraMayor(a, x);
53 int veces = hasta - desde;
54 if (veces <= 0) System.out.println(x + " no está; iría en la posición " + desde);
55 else if (veces == 1) System.out.println(x + " aparece 1 vez, en la posición " + desde);
56 else System.out.println(x + " aparece " + veces + " veces, de la posición " + desde + " a la " + (hasta - 1));
57 }
58 }
59}primeraMayorOIgual y primeraMayor buscan dos fronteras del array: dónde empiezan los valores ≥ x y dónde empiezan los > x. Entre las dos están exactamente las apariciones de x, y si coinciden, x no está y esa es su posición de inserción.
Cada consulta cuesta dos búsquedas de O(log n), aunque x aparezca miles de veces: recorrer las repeticiones desde una aparición cualquiera sería O(n).
2. La capacidad mínima del camión
Un camión reparte paquetes en un orden fijo: cada día carga paquetes seguidos hasta que el siguiente ya no cabe, y no puede saltarse ninguno. ¿Cuál es la capacidad mínima del camión para repartirlo todo en D días como mucho? Resuélvelo con búsqueda binaria sobre la respuesta: la capacidad está entre el paquete más pesado y la suma de todos, y si una capacidad sirve, también sirven todas las mayores. El reparto y la salida ya están escritos: completa cabe y capacidadMinima.
- Línea 1: el número de días D. Línea 2: los pesos de los paquetes, en orden, separados por espacios.
- Salida:
Capacidad mínima: Cy, por cada día,Día N: p1 + p2 + … = total; si sobran días,Sobran K días(1 día). - Errores:
Días no válidos,No hay paquetesoPeso no válido: «texto»(los pesos son enteros mayores que 0).
Ejemplo
5 1 2 3 4 5 6 7 8 9 10
Capacidad mínima: 15 Día 1: 1 + 2 + 3 + 4 + 5 = 15 Día 2: 6 + 7 = 13 Día 3: 8 = 8 Día 4: 9 = 9 Día 5: 10 = 10
Ver la solución explicada
1import java.util.*;
2
3public class Main {
4 /** Reparte los paquetes en orden, llenando cada día hasta la capacidad (al menos un paquete por día). */
5 static List<List<Integer>> reparto(int[] p, int capacidad) {
6 List<List<Integer>> dias = new ArrayList<>();
7 List<Integer> hoy = new ArrayList<>();
8 int carga = 0;
9 for (int x : p) {
10 if (!hoy.isEmpty() && carga + x > capacidad) {
11 dias.add(hoy);
12 hoy = new ArrayList<>();
13 carga = 0;
14 }
15 hoy.add(x);
16 carga += x;
17 }
18 if (!hoy.isEmpty()) dias.add(hoy);
19 return dias;
20 }
21
22 /** ¿Se pueden repartir los paquetes en como mucho «dias» días con esa capacidad? */
23 static boolean cabe(int[] p, int dias, int capacidad) {
24 int usados = 1, carga = 0;
25 for (int x : p) {
26 if (x > capacidad) return false;
27 if (carga + x > capacidad) {
28 usados++;
29 carga = 0;
30 }
31 carga += x;
32 }
33 return usados <= dias;
34 }
35
36 /** Búsqueda binaria sobre la respuesta: la capacidad mínima está entre el paquete más pesado y la suma. */
37 static int capacidadMinima(int[] p, int dias) {
38 int izq = Arrays.stream(p).max().getAsInt(), der = Arrays.stream(p).sum();
39 while (izq < der) {
40 int medio = izq + (der - izq) / 2;
41 if (cabe(p, dias, medio)) der = medio; // vale: quizá también una menor
42 else izq = medio + 1; // no vale: hace falta más
43 }
44 return izq;
45 }
46
47 public static void main(String[] args) {
48 Scanner sc = new Scanner(System.in);
49 int dias;
50 try {
51 dias = Integer.parseInt(sc.nextLine().trim());
52 } catch (Exception e) {
53 dias = 0;
54 }
55 if (dias <= 0) {
56 System.out.println("Días no válidos");
57 return;
58 }
59 String linea = sc.hasNextLine() ? sc.nextLine().trim() : "";
60 if (linea.isEmpty()) {
61 System.out.println("No hay paquetes");
62 return;
63 }
64 String[] partes = linea.split("\\s+");
65 int[] p = new int[partes.length];
66 for (int i = 0; i < partes.length; i++) {
67 try {
68 p[i] = Integer.parseInt(partes[i]);
69 } catch (NumberFormatException e) {
70 p[i] = 0;
71 }
72 if (p[i] <= 0) {
73 System.out.println("Peso no válido: «" + partes[i] + "»");
74 return;
75 }
76 }
77 int c = capacidadMinima(p, dias);
78 System.out.println("Capacidad mínima: " + c);
79 List<List<Integer>> r = reparto(p, c);
80 for (int i = 0; i < r.size(); i++) {
81 List<Integer> d = r.get(i);
82 int suma = d.stream().mapToInt(Integer::intValue).sum();
83 System.out.println("Día " + (i + 1) + ": " + String.join(" + ", d.stream().map(String::valueOf).toList()) + " = " + suma);
84 }
85 if (r.size() < dias) System.out.println("Sobran " + (dias - r.size()) + (dias - r.size() == 1 ? " día" : " días"));
86 }
87}La clave es la monotonía: si con capacidad C se puede, con C + 1 también. Eso convierte «encontrar la mínima» en buscar una frontera en el rango de capacidades posibles, como en un array ordenado de «no, no, no, sí, sí, sí».
Cada comprobación recorre los n paquetes, y hacen falta log₂(suma − máximo) comprobaciones: O(n log S). Probar todas las capacidades una a una sería O(n · S).
Test
Test: Búsqueda binaria
0/5 respondidas · 0 aciertosElige una respuesta en cada pregunta: verás al momento si es correcta y por qué. Con un 80 % de aciertos se da por superada.
1.¿Qué condición tienen que cumplir los datos para usar la búsqueda binaria?
2.¿Cuántas comparaciones necesita, como mucho, para buscar en un array ordenado de un millón de elementos?
3.¿Por qué se calcula el medio con
izq + (der - izq) / 2en lugar de(izq + der) / 2?4.
Arrays.binarySearch(new int[]{2, 4, 6}, 5)devuelve:5.Tienes un array desordenado y vas a buscar un único valor. ¿Qué es mejor?