Introducción

1

Patrones de Arreglos y Strings: Ventana Deslizante y Dos Apuntadores

2

Arrays y Strings: Funcionamiento y Complejidades Temporales

Dos Apuntadores

3

Patrón de Dos Apuntadores en Algoritmos de Lista

4

Verificación de Orden en Diccionario Alienígena

5

Ordenamiento de Palabras en Idiomas Alienígenas

6

Playground: Verifying Alien Dictionary

7

Ordenación de Palabras en Diccionario Alienígena

8

Combinar Listas Ordenadas en un Array Ascendente

9

Ordenamiento de Listas con Complejidad Óptima y Espacio Constante

10

Playground: Merge Two Sorted Lists

11

Intercalación de Listas Ordenadas en Python

12

Resolver el problema "Container with Most Water" en Python

13

Cálculo Óptimo de Área en Listas de Alturas

14

Playground: Container with Most Water

15

Implementación de solución de cálculo de área máxima en Java

16

Implementación de Trapping Rainwater en Complejidad Lineal

17

Retos de Algoritmos con Apuntadores en Python

18

Patrones de Dos Apuntadores: Soluciones a Problemas Comunes en Python

Ventana Deslizante

19

Patrón Ventana Deslizante para Análisis de Datos Secuenciales

20

Subcadena más larga sin caracteres repetidos: patrón ventana deslizante

21

Algoritmo de Ventana Deslizante para Subcadenas Únicas

22

Playground: Longest Substring Without Repeating Characters

23

Algoritmo Python para Substring más Largo Sin Repeticiones

24

Retos de Algoritmos: Dos Apuntadores y Subcadenas

25

Máximos 1s Consecutivos y Subcadenas sin Repeticiones

Búsqueda Binaria

26

Algoritmo de búsqueda binaria en listas ordenadas

27

Búsqueda en Arrays Rotados: Encontrar Entero en Lista Ordenada

28

Búsqueda Binaria en Arreglos Rotados

29

Playground: Search in Rotated Arrays

30

Búsqueda en Arrays Rotados con C++

31

Búsqueda eficiente en matriz ordenada MxN

32

Búsqueda Binaria en Matrices 2D Ordenadas

33

Playground: Search 2D Array Matrix

34

Búsqueda Binaria en Matrices con Python

Próximos pasos

35

Estructuras de Datos Lineales: Conceptos y Aplicaciones

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Búsqueda en Arrays Rotados: Encontrar Entero en Lista Ordenada

27/35
Recursos

¿Qué es el problema "Search in Rotated Arrays"?

El problema "Search in Rotated Arrays" es un reto común en las entrevistas técnicas y desafíos de programación. Se trata de trabajar con una lista de enteros que está ordenada de manera ascendente, pero que ha sido rotada en un índice desconocido. Esta rotación da como resultado una lista en la que los números parece que están desordenados, aunque en realidad mantiene un patrón de orden. El objetivo del problema es encontrar un número dentro de esta lista rotada y, si no lo encontramos, debemos retornar -1.

¿Cómo se estructura el array rotado?

Cuando hablamos de un array rotado, nos referimos a una lista que originalmente está ordenada y que se ha modificado rotando sus elementos desde un punto de pivote. Por ejemplo, si tenemos la lista original [0, 1, 2, 4, 5, 6, 7], y esta rotara en el pivote 3, el resultado sería [4, 5, 6, 7, 0, 1, 2]. Este tipo de rotación conserva el orden relativo de los elementos dentro de sus nuevos segmentos.

  • Lista Original: [0, 1, 2, 4, 5, 6, 7]
  • Lista Rotada: [4, 5, 6, 7, 0, 1, 2]

¿Cómo resolver el problema utilizando búsqueda binaria?

Aunque la lista rotada no parece estar ordenada a simple vista, se puede aplicar la técnica de búsqueda binaria debido a su estructura rotada. La búsqueda binaria es un algoritmo eficiente que se utiliza generalmente en listas ordenadas, lo que nos permite encontrar el índice de un elemento en un tiempo O(log n). Aquí se aprovecha el hecho de que una parte de la lista siempre estará ordenada.

Procedimiento de búsqueda binaria para arrays rotados

  1. Identificación del segmento ordenado:

    • Comparamos los elementos ubicados al inicio y al final de la lista para determinar cuál segmento está ordenado de manera ascendente.
  2. Determinación del pivote:

    • Utilizamos los índices medios para revisar si estamos en el segmento ordenado o en el segmento desordenado.
  3. Comparación del objetivo:

    • Buscamos el objetivo comparando en qué parte de la lista rotada se encuentra, revisando si está dentro de los límites del segmento ordenado.
  4. Encuentra o retorna -1:

    • Si el objetivo se encuentra en el segmento ordenado, ajustamos los índices para seguir buscando en ese segmento. Si no aparece en ninguno de los pasos, retornamos -1.

Ejemplo práctico

  • Dada la lista rotada [4, 5, 6, 7, 0, 1, 2], queremos buscar el número 0.
    • Al aplicar búsqueda binaria y reconocer el segmento ordenado, rápidamente encontramos que el 0 está en la posición 4.

¿Qué hacer si el elemento no está en la lista?

Si tras aplicar el algoritmo de búsqueda binaria no encontramos el elemento que buscamos, la implementación debe retornar -1 para indicar que el elemento objetivo no se encuentra dentro del array rotado.

Este tipo de ejercicio es fundamental para quienes buscan practicar técnicas avanzadas de búsqueda y manipulación de datos en listas y arrays. ¡Así que anímate a intentarlo y a perfeccionar tus habilidades de programación!

Aportes 4

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Propongo solución en Python: ``` from typing import List def search\_in\_rotated\_array(nums: List\[int], target: int) -> int: if len(nums) == 1: return 0 if nums\[0] == target else -1 left = 0 right = len(nums) - 1 while left <= right: middle = (left + right) // 2 if nums\[middle] == target: return middle if nums\[left] <= nums\[middle]: # \* left half is sorted if nums\[left] <= target < nums\[middle]: right = middle - 1 else: left = middle + 1 else: # \* right half is sorted if nums\[middle] < target <= nums\[right]: left = middle + 1 else: right = middle - 1 return -1 ```

Esta es mi solución en Java:

public class SearchInRotatedArrays {

    public static int busquedaBinaria(int[] nums, int izquierda, int derecha, int target) {
        int mitad;
        while (izquierda <= derecha) {
            mitad = izquierda + (derecha - izquierda) / 2;

            if (nums[mitad] == target) {
                return mitad;
            } else if (nums[mitad] < target) {
                izquierda = mitad + 1;
            } else {
                derecha = mitad - 1;
            }
        }
        return -1;
    }

    public static int[] rotarArreglo(int[] nums, int k) {
        int[] numsRot = new int[nums.length];
        for (int i = k, j = 0; i < nums.length; i++, j++) {
            numsRot[j] = nums[i];
        }

        for (int i = 0, j = k + 1; i < k; i++, j++) {
            numsRot[j] = nums[i];
        }

        return numsRot;
    }

    public static int buscarEnArregloRotado(int[] nums, int k, int target) {
        int izquierda = 0;
        int derecha = k;

        if (nums[izquierda] == target) {
            return izquierda;
        }

        if (nums[derecha] == target) {
            return derecha;
        }

        if (target <= nums[derecha] && target >= nums[izquierda]) {
            return busquedaBinaria(nums, izquierda, derecha, target);
        }

        izquierda = k + 1;
        derecha = nums.length - 1;

        if (nums[izquierda] == target) {
            return izquierda;
        }

        if (nums[derecha] == target) {
            return derecha;
        }

        if (target <= nums[derecha] && target >= nums[izquierda]) {
            return busquedaBinaria(nums, izquierda, derecha, target);
        }

        return -1;
    }

    public static void main(String[] args) {
        int[] nums = {0, 1, 2, 4, 5, 6, 7};
        int k = 3;

        int[] numsRot = rotarArreglo(nums, k);
        System.out.println(Arrays.toString(numsRot));

        int target = 0;

        int numBuscado = buscarEnArregloRotado(numsRot, k, target);
        System.out.println("Target: " + target + ", num buscado: " + numBuscado);

        target = 3;
        numBuscado = buscarEnArregloRotado(numsRot, k, target);
        System.out.println("Target: " + target + ", num buscado: " + numBuscado);
    }
}

En lo personal le agregaría una variante, me imagino que ya existe, que sería busque la mitad y vecinos. Con esto no estoy buscando solo 1 valor sino 3 cada vez que divido.
.
Big O notation sigue siendo O(log n)


Hola, esta es la solución a la que llegué.

  1. Comenzaríamos con dos apuntadores a los extremos.
    • i: Apuntador izquierdo, comienza en 0.
    • d: Apuntador derecho, comienza en len(s) - 1.
  2. Calculamos la posición del punto medio m = (i + d) // 2.

Antes de pasar al siguiente paso, podemos ver que m divide al array en dos partes diferentes o rangos. Utilizando los dos apuntadores extremos podemos conocer algo importante: cuál de las dos partes está ordenada. Para esto tendríamos dos casos:

  • nums[m] < nums[d]: El arreglo esá ordenado en el rango de números desde m hasta d, pero no podemos asegurar nada con los números restantes.
  • nums[m] > nums[i]: El arreglo está ordenado en el rango de números desde i hasta m, pero no podemos asegurar nada con los restantes.

Una vez que conocemos qué rango está ordenado, podemos preguntarnos: ¿el número que busco está dentro del rango ordenado? Si la respuesta es afirmativa entonces continuamos la búsqueda en ese rango de valores, si no, es probable que el número que buscamos esté en el otro rango, el cual no conocemos a partir de qué valor está ordenado.

  1. Antes de mover los apuntadores, podemos revisar si el valor que buscamos está en i, m o d. Si no, entonces actualizamos alguno de los apuntadores extremos.
  2. Para actualizar alguno de los apuntadores extremos (i o d) se siguen las siguientes condiciones:
    • target está en el rango ordenado:
      • Si el rango ordenado era [m, d] entonces movemos a i usando i = m + 1.
      • Si el rango ordenado era [i, m] entonces movemos a d usando d = m - 1.
    • target no está en el rango ordenado:
      • Si el rango ordenado era [m, d], entonces movemos a d usando d = m - 1.
      • Si el rango ordenado era [i, m], entonces movemos a i usando i = m + 1.

Esto lo repetimos hasta encontrar al número que buscamos o hasta que los dos apuntadores estén juntos.

En resumen, sería buscar qué rango de valores está ordenado y si nuestro número está en ese rango, continuaríamos como una búsqueda binaria normal. En caso de que no esté en el rango ordenado, entonces buscaríamos en el rango faltante, volviendo a verificar el orden de los números y si el valor que buscamos se encuentra en ese rango.