33. Búsqueda de matrices ordenadas rotadas y 81. Búsqueda de matrices ordenadas rotadas II ●●

33. Búsqueda de una matriz ordenada rotada

describir

Los números de la matriz de enteros están ordenados en orden ascendente y los valores de la matriz son diferentes entre sí .

Antes de pasar a la función, nums se rota en un subíndice predesconocido k (0 <= k < nums.length) , de modo que la matriz se convierte en [nums[k], nums[k+1],…, nums[ n-1], nums[0], nums[1],…, nums[k-1]] (los subíndices comienzan a contar desde 0).
Por ejemplo, [0,1,2,4,5,6,7] podría convertirse en [4,5,6,7,0,1,2] después de la rotación en el índice 3.

Proporcione los números de matriz rotados y un objetivo entero; si el valor objetivo existe en nums , devuelva su subíndice ; de ​​lo contrario, devuelva -1 .

Tienes que diseñar un algoritmo con complejidad temporal O (log n) para resolver este problema.

ejemplo

Entrada: números = [4,5,6,7,0,1,2], objetivo = 0
Salida: 4

Entrada: números = [4,5,6,7,0,1,2], objetivo = 3
Salida: -1

respuesta

dicotomía

Para matrices ordenadas, puede utilizar el método de búsqueda binaria para buscar elementos.

Pero en esta pregunta, la matriz en sí no está en orden y solo se garantiza que una parte de la matriz estará en orden después de la rotación.

Cuando dividimos la matriz en partes izquierda y derecha desde el medio, debe haber una parte de la matriz que esté en orden .

Esto sugiere que podemos comprobar qué parte de las dos partes [l, mid] y [mid + 1, r] separadas por el mid actual como posición dividida está en orden durante la búsqueda binaria convencional, y qué parte está en orden según Comparación del tamaño de la parte objetivo para determinar cómo debemos cambiar los límites superior e inferior de la búsqueda binaria, porque podemos juzgar si el objetivo está en esta parte de acuerdo con la parte ordenada:
inserte la descripción de la imagen aquí

  • Si [l, mid - 1] es una matriz ordenada y el tamaño del objetivo satisface [nums[l], nums[mid]), entonces debemos limitar el rango de búsqueda a [l, mid - 1]; de lo contrario, en [ mid + 1, r] para encontrar.
  • Si [mid, r] es una matriz ordenada y el tamaño del objetivo satisface (nums[mid+1], nums[r]], entonces debemos limitar el rango de búsqueda a [mid + 1, r]; de lo contrario, en [ l , mid - 1] para encontrar.

El tamaño de la parte de evaluación en el código La izquierda y la derecha de la parte de evaluación se pueden reemplazar por 0 y n-1, el efecto es el mismo y se utilizan para determinar dónde está la parte ordenada .

  • Complejidad del tiempo: O (logn), donde n es el tamaño de la matriz de números. La complejidad temporal de todo el algoritmo es la complejidad temporal O (logn) de la búsqueda binaria.
  • Complejidad espacial: O(1) . Sólo necesitamos un nivel constante de espacio para las variables.
class Solution {
    
    
public:
    int search(vector<int>& nums, int target) {
    
    
        int n = nums.size();
        int left = 0, right = n-1;
        while(left <= right){
    
    
            int mid = (right + left) >> 1;
            if(nums[mid] == target) return mid;                 // 目标索引
            if(nums[left] <= nums[mid]){
    
                            // 左半边有序,<=
                if(target >= nums[left] && target < nums[mid]){
    
     // target 在左半边,mid不是目标索引,因此不需要=判断,下同
                    right = mid - 1;
                }else{
    
    
                    left = mid + 1;
                }
            }else{
    
      // if(nums[0] > nums[mid])                  // 右半边有序
                if(target > nums[mid] && target <= nums[right]){
    
    // target 在右半边
                    left = mid + 1;
                }else{
    
    
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
};

81. Búsqueda de matrices ordenadas rotadas II

describir

Los números de la matriz de enteros están ordenados en orden ascendente y puede haber valores duplicados en la matriz .

Proporcione los números de matriz rotados y un objetivo entero; si el valor objetivo existe en nums , devuelva verdadero ; de lo contrario, devuelva falso .

ejemplo

Entrada: números = [2,5,6,0,0,1,2], objetivo = 0
Salida: verdadero

respuesta

dicotomía

Para el caso en el que hay elementos repetidos en la matriz, puede haber a[l]=a[mid]=a[r] durante la búsqueda binaria. En este momento, es imposible juzgar cuál del intervalo [l, mid ] y el intervalo [mid+1, r] está en orden.

Por ejemplo, nums=[3,1,2,3,3,3,3], target=2, es imposible juzgar si el intervalo [0,3] o el intervalo [4,6] están en orden La primera dicotomía.

En este caso, solo podemos sumar uno al límite izquierdo del intervalo binario actual, restar uno del límite derecho y luego continuar la búsqueda binaria en el nuevo intervalo.

class Solution {
    
    
public:
    bool search(vector<int>& nums, int target) {
    
    
        int n = nums.size();
        int left = 0, right = n-1;
        while(left <= right){
    
    
            int mid = (left + right) >> 1;
            if(nums[mid] == target) return true;
            if(nums[left] == nums[mid] && nums[mid] == nums[right]){
    
        // 无法判断有序部分
                ++left;
                --right;
            }else if(nums[left] <= nums[mid]){
    
    							// 左边有序
                if(target >= nums[left] && target < nums[mid]){
    
    			// 有序部分判断,target 在左半边
                    right = mid - 1;
                }else{
    
    
                    left = mid + 1;
                }
            }else{
    
    														// 右边有序
                if(target > nums[mid] && target <= nums[right]){
    
    		// 有序部分判断,target 在右半边
                    left = mid + 1;
                }else{
    
    
                    right = mid - 1;
                }
            }
        }
        return false;
    }
};

mientras (izquierda <derecha)

#include <vector>
using std::vector;

// 二分寻找
//
// 解题思路:
//  第一类
//      10111和11101这种。此种情况下 "nums[start] == nums[mid]",分不清到底是前面有序还是后面有
//      序,此时! start++即啊。相当于去掉一个重复的干扰项。
//  第二类
//      2345671这种,也就 "是nums[start] < nums[mid]"。此例子中就是2 < 5 ;
//      这种情况下,前半部分有序。因此如果nums[start] <=target<nums [mid],则在前半部分找,否则去后半部分找。
//  第三类
//      6712345这种,也就是nums[start] > nums[mid]。此例子中就是6 > 2 ;
//      这种情况下,后半部分有序。因此如果nums [mid] <target<=nums[end] 。则在后半部分找,否则去前半部分找。

class Solution {
    
    
public:
    bool search(vector<int>& nums, int target) {
    
    
        int len = nums.size();
        int left = 0, right = len - 1;

        while (left < right) {
    
    
            int mid = left + (right - left) / 2;  // mid偏向与左边, 使用left=mid+1,right=mid
            // 判断是否找到
            if (nums[mid] == target) {
    
    
                return true;
            }
            // 是否为第一类情况
            if (nums[left] == nums[mid]) {
    
    
                ++left;
                continue;
            }

            // 前半部分有序 (注:只有在有序部分中判断target,才判断出target是在前半部分还是在后半部分!)
            if (nums[left] < nums[mid]) {
    
    
                if (target >= nums[left] && target < nums[mid]) {
    
    
                    right = mid;
                }
                else {
    
    
                    left = mid + 1;
                }
            }
            // 后半部分有序
            else {
    
    
                if (target > nums[mid] && target <= nums[right]) {
    
    
                    left = mid + 1;
                }
                else {
    
    
                    right = mid;
                }
            }
        }

        return nums[left] == target ? true : false;  // 存在因 left==right 而退出循环,从而没有判断nums[mid] == target的情况

    }
};

Supongo que te gusta

Origin blog.csdn.net/qq_19887221/article/details/126271380
Recomendado
Clasificación