[Algoritmo] Dicotomía ② (Encuentre el valor objetivo en la matriz ordenada | Escritura clásica de la dicotomía | Encuentre la última posición del elemento en la matriz ordenada | Plantilla general de la dicotomía)





1. Encuentre el valor objetivo en la matriz ordenada (forma clásica de dicotomía)



https://leetcode.cn/problems/binary-search/

Tema típico de búsqueda binaria: encuentre un valor de destino de una matriz ordenada , devuelva el valor de índice del elemento de destino en la matriz y devuelva -1 si el valor de destino no existe en la matriz ;

Por ejemplo: busque el valor objetivo 2 de [1, 2, 4, 5, 6] y devuelva el índice del elemento de matriz correspondiente a 2 como 1; si busca 3 de la matriz anterior y no hay dicho elemento en la matriz, devuelve -1;


Implementación clásica de dicotomía:

public class Solution {
    
    
    public int search(int[] nums, int target) {
    
    
        // 1. 判断参数合法性
        if(nums == null || nums.length == 0) {
    
    
            return -1;
        }

        // 2. 二分查找的范围
        int start = 0, end = nums.length - 1;

        // 3. 开始循环进行二分查找
        while(start <= end) {
    
    
            // 3.1 计算中间索引
            int mid = start + (end - start) / 2;
            // 3.2 对比中间元素与目标值
            if(nums[mid] == target) {
    
    
                // 如果 中心元素 = 目标值 , 找到了目标元素 , 直接返回该索引值
                return mid;
            } else if(nums[mid] > target) {
    
    
                // 如果 中心元素 > 目标值 , 则需要去 该查找区间的 左侧继续查找
                end = mid - 1;
            } else {
    
    
                // 如果 中心元素 < 目标值 , 则需要去 该查找区间的 右侧继续查找
                start = mid + 1;
            }
        }

        // 4. 循环完毕 , 说明最终 start > end , 没有找到目标值
        return -1;
    }
}

La dicotomía anterior se realiza y es posible encontrar el valor objetivo en la matriz sin valor repetido;

Si el valor a buscar en el arreglo se repite, se requiere devolver un índice específico entre estos valores, como: devolver el último, devolver el primero, devolver el enésimo, y otros requisitos adicionales, la dicotomía anterior no se puede lograr;





2. Encuentra la última posición de un elemento en una matriz ordenada (plantilla general para dicotomía)



Encuentre la última posición de un elemento en una matriz ordenada : encuentre un valor objetivo de una matriz ordenada , devuelva el valor de índice del elemento objetivo en la matriz y los elementos se pueden repetir,

  • Si el valor de destino no existe en la matriz , devuelve -1;
  • Debe diseñar e implementar un algoritmo con complejidad de tiempo O(log n) para resolver este problema.

Por ejemplo: encuentre el valor objetivo 2 de [1, 2, 2, 4, 5, 6] y devuelva el índice del elemento de matriz correspondiente a 2 es 1 y 2, aquí se busca la última posición y el resultado es 2; si de la matriz anterior encuentra 3 en la matriz, si no hay tal elemento en la matriz, entonces devuelve -1;


El tema anterior requiere una complejidad de tiempo de O ( log ⁡ n ) O(\log n)O ( lo gn ) , en el blog anterior[Algoritmo] Dicotomía ① (Introducción al principio básico de dicotomía | Comparación entre dicotomía y tabla hash | Complejidad de tiempo correspondiente a algoritmos comunes)mencionó que la complejidad de tiempo de algoritmos comunes es la siguiente, tiempo El orden de complejidad de pequeño a grande es:

  • O(1) O(1)O ( 1 ) :operaciones de bits,búsquedas en tablas hash
  • O ( Iniciar sesión ⁡ norte ) O(\ Iniciar sesión n)O ( lo gn ) :dicotomía,algoritmo de potencia rápida,método de rodadura y división, método de multiplicación;
  • O (n) O (n)O ( n ) :método de enumeración,algoritmo de pila monotono, algoritmo dedoble puntero;
  • O ( norte Iniciar sesión ⁡ norte ) O(n \log norte)O ( niniciar sesiónn ) :clasificación rápida, clasificaciónpor fusión, clasificaciónpor montón;
  • O ( norte 2 ) O (n ^ 2)O ( n2 ):método de enumeración, programación dinámica;
  • O ( norte 3 ) O (n ^ 3)O ( n3 ):método de enumeración, programación dinámica;
  • O (2n) O(2^n)O ( 2n ):Combinación de preguntas de búsqueda relacionadas;
  • O (n!) O(n!)O ( n !) :Problemas de búsqueda relacionados con la permutación;

Obviamente, es necesario elegir el método de dicotomía para resolver los problemas de algoritmo anteriores;


Ejemplo de código:

package cn.zkhw.schedule.utils;

public class Solution {
    
    
    public int search(int[] nums, int target) {
    
    
        // 1. 判断参数合法性
        if(nums == null || nums.length == 0) {
    
    
            return -1;
        }

        // 2. 二分查找的范围
        int start = 0, end = nums.length - 1;

        // 3. 开始循环进行二分查找
        // 此处注意 start 和 end 区间需要能覆盖住所有目标值
        // 该循环条件很重要 , 是通用模板
        // ★ 要点一 : 此处尽量不要使用 start <= end 或 start < end 作为循环判定条件 , 在某些情况下会执行失败
        // 为了让程序有更多的适应性 , 这里使用 start + 1 < end 作为循环判定条件 , 可以有效避免死循环
        while(start + 1 < end) {
    
    
            // 3.1 计算中间索引
            // ★ 要点二 : 此处尽量不要使用 (start + end) / 2 , 如果 两个数值都接近 Int.MAX_VALUE 则会溢出
            int mid = start + (end - start) / 2;
            // 3.2 对比中间元素与目标值
            if(nums[mid] == target) {
    
    
                // 如果 中心元素 = 目标值 , 找到了目标元素的第一个位置
                end = mid;
            } else if(nums[mid] > target) {
    
    
                // 如果 中心元素 > 目标值 , 则需要去 该查找区间的 左侧继续查找
                // ★ 要点三 : 由于循环判定条件是 start + 1 < end , 此处 end 赋值可以不使用 mid - 1
                end = mid;
            } else {
    
    
                // 如果 中心元素 < 目标值 , 则需要去 该查找区间的 右侧继续查找
                // ★ 要点四 : 由于循环判定条件是 start + 1 < end , 此处 start 赋值可以不使用 mid + 1
                start = mid;
            }
        }

        // 4. ★ 要点五 : 循环完毕 , 判定 start 和 end 是不是要找的值
        // 如果数组只有两个数的情况下 
        // while(start + 1 < end) 循环控制条件中的 start + 1 < end 直接为 false 
        // 循环直接退出 , 此处判定一下 start 和 end 是不是要找的值 
        if(nums[start] == target) {
    
    
            return -1;
        }
        if(nums[end] == target) {
    
    
            return -1;
        }

        // 5. 没有找到目标值
        return -1;
    }
}

Supongo que te gusta

Origin blog.csdn.net/han1202012/article/details/128780169
Recomendado
Clasificación