Problema de Leetcode solution-42. Atrapa la lluvia

Enlace de tema

Descripción del Título:

Dado n números enteros no negativos que representan el mapa de altura de cada columna con un ancho de 1, calcule cuánta agua de lluvia pueden recibir las columnas dispuestas de esta manera.
Inserte la descripción de la imagen aquí

Ejemplo:

Entrada: [0,1,0,2,1,0,1,3,2,1,2,1]
Salida: 6


violencia

  El método violento es más fácil de pensar, es decir, calcular cuánta agua de lluvia puede contener la columna actual por columna. Encuentre la altura máxima del extremo izquierdo y la altura máxima del curMaxLeftextremo derecho de la columna actual curMaxRight, compare el valor mínimo de la altura máxima en ambos extremos y compárelo con la altura de la columna actual. Si el valor mínimo es mayor que la altura actual, la diferencia es obviamente la cantidad de agua de lluvia, de lo contrario, no hay agua de lluvia Pack.


Código

class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        if(height.size() < 3)
            return 0;
            
        int len = height.size();
        int start = 0;
        while(start < len && height[start] == 0)
            start++;
        
        int curMaxLeft = height[start];
        int result = 0;

        for(int i = start + 1; i < len - 1; i++){
    
    
            int curMaxRight = getMax(height, i + 1, len - 1);
            int curHeight = min(curMaxLeft, curMaxRight);
            if(curHeight - height[i] > 0)
                result += curHeight - height[i];
            curMaxLeft = max(curMaxLeft, height[i]);
        }

        return result;

    }

private:
    int getMax(vector<int>& height, int start, int end){
    
    
        int result = 0;
        for(int i = start; i <= end; i++){
    
    
            result = max(result, height[i]);
        }

        return result;
    }
};

Optimización violenta

  En el método de fuerza bruta, encontramos que debemos obtener constantemente la altura máxima de los extremos izquierdo y derecho de la columna actual. Podemos usar una nota para registrar la altura máxima de los extremos izquierdo y derecho de la columna actual para evitar cálculos repetidos.

curMaxLeft [i] = max (curMaxLeft [i - 1], altura [i - 1]);
curMaxRight [i] = max (curMaxRight [i + 1], altura [i + 1]);


Código

class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        if(height.size() < 3)
            return 0;
        
        int result = 0;
        int len = height.size();
        vector<int> curMaxLeft(len);
        vector<int> curMaxRight(len);       

        for(int i = 1; i < len - 1; i++)
            curMaxLeft[i] = max(curMaxLeft[i - 1], height[i - 1]);
        
        for(int i = len - 2; i >= 0; i--)
            curMaxRight[i] = max(curMaxRight[i + 1], height[i + 1]);
        
        for(int i = 1; i < len - 1; i++){
    
    
            int cur = min(curMaxLeft[i], curMaxRight[i]);
            if(cur - height[i] > 0)
                result += cur - height[i];
        }

        return result;

    }
};

Optimización de dos punteros

  Ahora considere reducir la complejidad del espacio. Al observar las dos primeras soluciones violentas, encontramos que podemos usar el puntero para actualizar el valor máximo en el extremo izquierdo en tiempo real, pero no en el extremo derecho, porque el valor máximo en el extremo izquierdo se recorre de izquierda a derecha, y el máximo en el extremo derecho se recorre de derecha a izquierda, una vez La dirección del ciclo es de izquierda a derecha Obviamente, el método de violencia no puede completar la tarea en un ciclo.
  En este momento, consideramos punteros duales, que en realidad es una optimización del memo. En la nota, primero registramos el resultado y luego lo calculamos, y actualizamos el puntero doble en tiempo real.

Código

class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
        if(height.size() < 3)
            return 0;
        
        int result = 0;
        int len = height.size();
        
        int left = 0, right = len - 1;
        int curMaxLeft = height[0], curMaxRight = height[len - 1];

        while(left <= right){
    
    
            curMaxLeft = max(curMaxLeft, height[left]);
            curMaxRight = max(curMaxRight, height[right]);

            if(curMaxLeft > curMaxRight){
    
    
                result += curMaxRight - height[right];
                right--;
            }
            else{
    
    
                result += curMaxLeft - height[left];
                left++;
            }
        }

        return result;

    }
};


Link de referencia


Si hay errores o no es riguroso, corrígeme, muchas gracias.
Mi blog: http://breadhunter.gitee.io

Supongo que te gusta

Origin blog.csdn.net/weixin_40807714/article/details/105308209
Recomendado
Clasificación