[Algoritmo] Plantilla de código de ventana deslizante, resuelve fácilmente 80 preguntas de LeetCode

Prefacio:

Una ventana deslizante es un caso especial de un puntero doble, que se puede llamar puntero izquierdo y derecho. En cualquier momento, solo un puntero se mueve mientras que el otro permanece estacionario. El método de la ventana deslizante se usa generalmente para resolver el problema de las subsecuencias continuas calificadas en una secuencia específica.

La complejidad temporal de la ventana deslizante es lineal, generalmente O(n). Los límites izquierdo y derecho de la ventana deslizante no se deslizarán hacia la izquierda. Deslizar hacia la izquierda equivale a retroceder. Es un algoritmo de retroceso y puede caer en un bucle infinito. La ventana deslizante es una especie de problema transversal completo, que debe atravesarse hasta el final.

Su idea esencial radica en :

  1. Inicializar para llenar la ventana deslizante y obtener el valor objetivo de la primera ventana deslizante
  2. Continúe deslizando la ventana, y cada vez que la deslice hacia adelante, deberá eliminar y agregar un elemento para encontrar el valor objetivo óptimo.

1. Escenarios de aplicación de algoritmos

Palabras clave :

  1. Satisfacer la condición XXX (resultado del cálculo, número de ocurrencias, inclusión simultánea)
  2. más largo/más corto
  3. subcadena/subarreglo/subsecuencia

Por ejemplo: el subarreglo con la longitud más pequeña

2. Plantilla de idea de ventana corrediza

2.1 Ideas para usar ventanas corredizas (busca la más larga)

————Núcleo: Los punteros dobles izquierdo y derecho (L, R) están en el punto de inicio, y R se desliza hacia la derecha poco a poco para cambiar

———— Durante cada proceso de deslizamiento

Si: los elementos de la ventana cumplen las condiciones, R expande la ventana a la derecha y actualiza el resultado óptimo

Si: los elementos de la ventana no cumplen las condiciones, L encoge la ventana hacia la derecha

———R llega al final

2.2 La idea de usar ventana corredera (encontrar la más corta)

————Núcleo: Los punteros dobles izquierdo y derecho (L, R) están en el punto de inicio, y R se desliza hacia la derecha poco a poco para cambiar

———— Durante cada proceso de deslizamiento

Si: los elementos de la ventana cumplen las condiciones, L reduce la ventana a la derecha y actualiza el resultado óptimo

Si: los elementos de la ventana no cumplen las condiciones, R expande la ventana a la derecha

———R llega al final

3. Plantilla de código de ventana deslizante

3.1, la plantilla más larga

初始化 left,right,result,bestResult
while("右指针没有到结尾"){
    窗口扩大,加入right对应元素,更新当前result
    while("result不满足要求"){
        窗口缩小,移除left对应元素,left右移
    }
    更新最优结果bestResult
    right++;
}
返回bestResult

3.2, la plantilla más corta

初始化 left,right,result,bestResult
while("右指针没有到结尾"){
    窗口扩大,加入right对应元素,更新当前result
    while("result满足要求"){
        更新最优结果bestResult
        窗口缩小,移除left对应元素,left右移
    }
    right++;
}
返回bestResult

4. Prueba pequeña (práctica de algoritmos)

Título: [209. Subarreglo de longitud mínima]

Dada una matriz de n enteros positivos y un objetivo entero positivo.

Encuentre el subarreglo continuo más pequeño [numsl, numsl+1, ..., numsr-1, numsr] cuya suma ≥ objetivo en este arreglo, y devuelva su longitud. Devuelve 0 si no existe ningún subarreglo coincidente.

Ejemplo 1:

输入: target = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的子数组。

Ejemplo 2:

输入: target = 4, nums = [1,4,4]
输出: 1

pista:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105

Implementación del algoritmo:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        // 初始化 left,right,result,bestResult
        // result是当前的currSum、bestResult为mixLength
        int left = 0, right = 0,currSum = 0, mixLength = 0;
        // 右指针没有到结尾
        while(right < nums.length){
            // 窗口扩大,加入right对应元素,更新当前
            currSum += nums[right];
            // result满足要求
            while(currSum >= target){
                // 更新最优结果mixLength
                if(right - left + 1 < mixLength || mixLength == 0){
                    mixLength = right - left + 1;
                }
                // 窗口缩小,移除left对应元素,left右移
                currSum = currSum - nums[left];
                left++;
            }
            // right++
            right++;
        }
        // 返回mixLength
        return mixLength;
    }
}

Cinco: Resumen:

5.1: LeetCode pregunta original 209 canal de práctica

Para obtener más ejercicios de algoritmos y plantillas de algoritmos, haga clic en mi GitHub . No es fácil de crear. Si lo encuentra útil, puede ayudar a solicitar un Destacado en GitHub . ¡Gracias aquí! También eres bienvenido a participar en la contribución del proyecto de aprendizaje LeetCode en mi github (chatea conmigo en privado), pueden trabajar juntos en el algoritmo y avanzar en el camino del aprendizaje.

Supongo que te gusta

Origin blog.csdn.net/gongzi_9/article/details/126033595
Recomendado
Clasificación