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.
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 curMaxLeft
extremo 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