Algoritmo y estructura de datos de C ++ (13) (pila monotónica)

pila monótona

Una pila monótona es una estructura de pila en la que los elementos de la pila se mantienen en un orden determinado mediante mantenimiento.

Por lo general, es para encontrar la posición del primer elemento a la derecha o izquierda de cualquier elemento que sea mayor o menor que él mismo en una matriz unidimensional. En este momento, tenemos que pensar que podemos usar una pila monótona.

La esencia de la pila monótona es el espacio para el tiempo, porque se necesita una pila para registrar los elementos incrementados o decrementados durante el proceso transversal, y la ventaja es que solo es necesario atravesarla una vez.

739. Temperatura diaria

Dada una matriz de números enteros Ts que representa la temperatura de cada día, devuelva una respuesta de matriz, donde respuesta [i] significa que para el i-ésimo día, la siguiente temperatura más alta aparecerá unos días después. Si la temperatura no aumenta después de eso, sustituya 0 en este lugar.

Entrada: temperaturas = [73,74,75,71,69,72,76,73]
Salida: [1,1,4,2,1,1,0,0]

1. Recorrido de fuerza bruta

De adelante hacia atrás, dos capas de bucles for, encuentre el primer subíndice de elemento más grande para comparar y calcular, la complejidad del tiempo es O ( n 2 ) O (n ^ 2)O ( n.2 )

2. Recorrido inverso

En el tema, el rango de temperatura está entre [30, 100] grados, recorre de atrás hacia adelante, mantiene una matriz al lado para registrar el índice mínimo a la temperatura actual y, al mismo tiempo, busca y registra el índice mínimo WarmerIndex con un temperatura más alta a la derecha.

  • Complejidad del tiempo: O (nm) O(nm)O ( nm ) , donde n es la longitud de la lista de temperaturas, m es la longitud de la siguiente matriz y la temperatura no supera los 100 en este problema. La lista de temperaturas se recorre a la inversa y, para cada valor de la lista de temperaturas, se debe recorrer la siguiente matriz una vez.
  • Complejidad espacial: O ( m ) O (m)O ( m ) , donde m es la longitud de la siguiente matriz. Además del valor de retorno, es necesario mantener una matriz de longitud m para registrar la posición del subíndice de la primera aparición de cada temperatura.
class Solution {
    
    
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
    
    
        int n = temperatures.size();
        vector<int> ans(n), next(101, INT_MAX);
        for (int i = n - 1; i >= 0; --i) {
    
    
            int warmerIndex = INT_MAX;
            for (int t = temperatures[i] + 1; t <= 100; ++t) {
    
    
                warmerIndex = min(warmerIndex, next[t]);
            }
            if (warmerIndex != INT_MAX) {
    
    
                ans[i] = warmerIndex - i;
            }
            next[temperatures[i]] = i;
        }
        return ans;
    }
};

3. Pila monótona

Mantenga una pila monótona que almacene subíndices y las temperaturas en la lista de temperaturas correspondientes a los subíndices desde la parte superior de la pila hasta la parte inferior de la pila aumentan secuencialmente .

Si un subíndice está en la pila monótona, significa que aún no se ha encontrado el siguiente subíndice de temperatura más alta.

Hay tres criterios principales para utilizar una pila monótona:

  1. El elemento atravesado actual T[i] es mayor que el elemento superior de la pila T[st.top()]:
    en este momento, el elemento actual T[i] es la primera temperatura más alta en el lado derecho del elemento superior de la pila, entonces la pila La parte superior aparece y calcula el número de días de espera, el bucle juzga hasta que se establece la monotonicidad de la pila y luego empuja el subíndice del elemento en la pila;

  2. El elemento atravesado actualmente T[i] es igual al elemento superior de la pila T[st.top()]:
    el subíndice del elemento se empuja directamente a la pila, esperando que una temperatura más alta rompa la monotonicidad de la pila;

  3. El elemento actualmente atravesado T[i] es más pequeño que el elemento superior T[st.top()]:
    el subíndice del elemento se empuja directamente a la pila, esperando que una temperatura más alta rompa la monotonicidad de la pila;

  • Complejidad del tiempo: O ( n ) O (n)O ( n ) donde n es la longitud de la lista de temperaturas. Recorra hacia adelante la lista de temperaturas una vez, para cada subíndice en la lista de temperaturas, hay como máximo una operación de presionar y hacer estallar.
  • Complejidad espacial: O ( n ) O (n)O ( n ) donde n es la longitud de la lista de temperaturas. Es necesario mantener una pila monótona para almacenar los subíndices en la lista de temperaturas.
class Solution {
    
    
public:
    vector<int> dailyTemperatures(vector<int>& Ts) {
    
    
        stack<int> st;
        int n = Ts.size();
        vector<int> ans(n, 0);
        for(int i = 0; i < n; ++i){
    
    
            while(!st.empty() && Ts[i] > Ts[st.top()]){
    
    		// 维护单调栈
                ans[st.top()] = i - st.top();
                st.pop();
            }
            st.push(i);    		// 栈内没有元素,或 入栈后单调性不变,下标直接入栈
        }
        return ans;
    }
};

496. Siguiente elemento mayor I ●

El siguiente elemento mayor del número x en nums1 se refiere al primer elemento mayor que x en el lado derecho de la posición correspondiente de x en nums2 .

Se le proporcionan dos matrices nums1 y nums2 sin elementos repetidos , indexadas desde 0, donde nums1 es un subconjunto de nums2 .

Para cada 0 <= i < nums1.length, encuentre el índice j que satisfaga nums1[i] == nums2[j] y determine el siguiente elemento mayor de nums2[j] en nums2. Si no hay un elemento siguiente mayor, entonces la respuesta a esta consulta es -1 .

Devuelve una matriz ans de longitud nums1.length como respuesta tal que ans[i] es el siguiente elemento mayor como se describe anteriormente.

Entrada: nums1 = [4,1,2], nums2 = [1,3,4,2]
Salida: [-1,3,-1]
Explicación: El siguiente elemento mayor de cada valor en nums1 es el siguiente Dijo :

  • 4, marcado en negrita cursiva, nums2 = [1,3,4,2]. No existe un siguiente elemento mayor, por lo que la respuesta es -1.
  • 1, marcado en negrita cursiva, nums2 = [1,3,4,2]. El siguiente elemento mayor es 3 .
  • 2, marcado en negrita cursiva, nums2 = [1,3,4,2]. No existe un siguiente elemento mayor, por lo que la respuesta es -1.

1. Recorrido de fuerza bruta

2. Pila monótona + hachís

Para encontrar el primer elemento más grande a la derecha, mantenga una pila monótona cuyo valor aumenta desde la parte superior de la pila hasta la parte inferior de la pila , de modo que cuando un elemento más grande rompa la monotonicidad , los elementos en la pila encuentren el primer elemento más grande a la derecha. elemento en los elementos correctos .

Primero recorra nums1 y asigne valores y subíndices de elementos para determinar si algunos elementos de nums2 existen en nums1, y también encuentre los subíndices de matriz correspondientes que se modifican directamente.

class Solution {
    
    
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
    
    
        int n1 = nums1.size(), n2 = nums2.size();
        vector<int> ret(n1, -1);
        stack<int> st;
        unordered_map<int, int> map;			// 哈希下标映射
        for(int i = 0; i < n1; ++i) map[nums1[i]] = i;
        for(int i = 0; i < n2; ++i){
    
    
            while(!st.empty() && st.top() < nums2[i]){
    
    		// 打破单调性
                if(map.count(st.top()) > 0) ret[map[st.top()]] = nums2[i];
                st.pop();
            }
            st.push(nums2[i]);					// 符合单调性,直接入栈
        }
        return ret;
    }
};

496. El siguiente gran elemento II ●

Dada una matriz circular de números (el siguiente elemento de nums[nums.length - 1] es nums[0]), devuelve el siguiente elemento mayor de cada elemento en nums.

El siguiente elemento mayor del número x es el primer número mayor después de este número en el orden transversal de la matriz , lo que significa que debes realizar un bucle para buscar su siguiente número mayor. Si no está presente, genera -1.

Entrada: nums = [1,2,1]
Salida: [2,-1,2]
Explicación: El siguiente número mayor del primer 1 es 2;
el número 2 no puede encontrar el siguiente número mayor
; El siguiente número mayor de dos Es necesario buscar 1 circularmente y el resultado también es 2.

1. Pila monótona

Notamos que en la solución de fuerza bruta, si la primera mitad de la matriz no aumenta monótonamente, habrá un gran desperdicio de recursos informáticos. Por ejemplo [6, 5, 4, 3, 8], para los números anteriores como [6, 5, 4, 3], debes recorrer hacia atrás, y cuando encuentres el elemento 8, encontrarás un elemento más grande que tú. ; y si se sabe que el elemento 6 encuentra el elemento 8 hacia atrás para encontrar un número mayor que él mismo, entonces para los elementos [5,4,3], todos son más pequeños que el elemento 6, por lo que el elemento mayor que ellos debe ser Para el elemento 8 , ¡no es necesario recorrer el par [5,4,3] hacia atrás una vez!

De acuerdo con el análisis anterior, podemos recorrer la matriz una vez. Si los elementos disminuyen monótonamente (su **"siguiente elemento más grande" es el mismo**), guardaremos estos elementos hasta que encontremos un elemento más grande; compare el más grande elemento con el elemento guardado uno por uno. Si el elemento es más grande, entonces es el "siguiente elemento más grande" del elemento anterior.

inserte la descripción de la imagen aquí
Hay dos implementaciones comunes de matrices en bucle:

  1. Copie la matriz al final de la matriz . Aunque esta no es una matriz circular estricta, es suficiente para esta pregunta, porque esta pregunta atraviesa la matriz como máximo dos veces.
  2. Utilice la operación de módulo % para asignar el subíndice i a 0-N de la longitud de los números de matriz.
class Solution {
    
    
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
    
    
        int n = nums.size();
        vector<int> ret(n, -1);
        stack<int> st;
        for(int i = 0; i < 2*n-1; ++i){
    
    
            while(!st.empty() && nums[i%n] > nums[st.top()%n]){
    
    	// 单调性破坏,找到更大值
                ret[st.top()%n] = nums[i%n];
                st.pop();
            }
            st.push(i);		// 栈中保存元素下标
        }
        return ret;
    }
};

Supongo que te gusta

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