Skip to Content

Pilas

Recursos
FuenteRecursoNotas
CPH4.5 - Stacks

descripción breve de las operaciones

CSAStack Introduction

Aplicación de matching de paréntesis

Pilas

Una pila es una estructura de datos Last In First Out (LIFO: último en entrar, primero en salir) que soporta tres operaciones, todas en O(1)\mathcal{O}(1). Se puede pensar como una pila real de papeles.

C++ 

  • push: agrega un elemento al tope de la pila
  • pop: saca un elemento del tope de la pila
  • top: obtiene el elemento del tope sin sacarlo
stack<int> s; s.push(1); // [1] s.push(13); // [1, 13] s.push(7); // [1, 13, 7] cout << s.top() << endl; // 7 s.pop(); // [1, 13] cout << s.size() << endl; // 2

Java

  • push: agrega un elemento al tope de la pila
  • pop: saca un elemento del tope de la pila
  • peek: obtiene el elemento del tope sin sacarlo
Stack<Integer> s = new Stack<Integer>(); s.push(1); // [1] s.push(13); // [1, 13] s.push(7); // [1, 13, 7] System.out.println(s.peek()); // 7 s.pop(); // [1, 13] System.out.println(s.size()); // 2

Python

Python no tiene un tipo pila integrado, pero una lista puede funcionar como pila.

  • list.append(): Agrega un elemento al final.
  • list[-1]: Obtiene el último elemento sin sacarlo.
  • list.pop(): Saca el último elemento y lo devuelve (pero no hace falta usar el valor devuelto).
  • list.pop(n): Saca el nn-ésimo elemento, indexado desde cero. Nótese que sacar elementos es una operación O(n).
stack = [] # [] stack.append(1) # [1] stack.append(2) # [1, 2] stack.append(3) # [1, 2, 3] v = stack[-1] # stack = [1, 2, 3] (sin cambios), v = 3 stack.pop() # [1, 2] v = stack.pop() # stack = [1], v = 2 stack.append(4) # [1, 4] v = stack.pop(0) # stack = [4], v = 1

Aplicación: elemento menor más cercano

HechoFuenteNombreDificultadTagsSolución
CSESNearest Smaller ValuesFácilStacken el módulo

Consideremos el siguiente problema:

Dado un arreglo aa de NN (1N1051 \le N \le 10^5) enteros, para cada índice ii, hallar el índice jj más a la derecha tal que j<ij < i y ai>aja_i > a_j.

Recursos
FuenteRecursoNotas
CPH8.2 - Nearest Smaller Element
CSAStack Application - Soldier's Row

aplicación similar con animación

Para resolver esto, guardamos una pila de pares valor,ıˊndicevalor, índice e iteramos el arreglo de izquierda a derecha. Para algún índice ii, calculamos ans[i]\texttt{ans}[i], el índice más a la derecha para ii, así:

  • Seguir sacando el elemento del tope de la pila mientras valoraivalor \ge a_i. Esto es porque sabemos que el par que contiene valorvalor nunca será la solución para ningún índice j>ij > i, ya que aia_i es menor o igual que valorvalor y tiene un índice más a la derecha.
  • Si valor<aivalor < a_i, fijar ans[i]\texttt{ans}[i] en ıˊndiceíndice, porque una pila guarda primero los valores agregados más recientemente (o en este caso, los más a la derecha), de modo que ıˊndiceíndice contendrá el valor más a la derecha que es menor que aia_i. Luego, agregar (ai,i)(a_i, i) a la pila.

La pila que usamos se llama pila monótona (monotonic stack) porque seguimos sacando el elemento del tope de la pila, lo que mantiene su monotonía (la misma propiedad que se necesita para algoritmos como la búsqueda binaria) porque los elementos de la pila son crecientes.

Implementación

Complejidad temporal: O(N)\mathcal{O}(N)

#include <bits/stdc++.h> using namespace std; int N; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> N; stack<pair<int, int>> stack; stack.push({0, 0}); for (int i = 1; i <= N; ++i) { int a; cin >> a; while (!stack.empty() && stack.top().first >= a) stack.pop(); cout << stack.top().second << " "; stack.push({a, i}); } }
/** * author: Kai Wang */ import java.io.*; import java.util.*; public class NearestSmallestVals { /** * Mantenemos una pila de pares (ind, value) * Recorremos el arreglo de izquierda a derecha y usamos ans para guardar * respuestas * Si el valor de a_i > (stk.peek()=a_k) entonces saco el tope de la * pila. Esto está bien porque para todo j>k, a_j>=a_k, o (j,a_j) está en * la pila. Si a_k < a_i entonces fijamos ans[i]=k e insertamos (i,a_i) * Nótese que los elementos de la pila están ordenados por índice * */ public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int N = Integer.parseInt(br.readLine()); int[] a = new int[N + 1]; StringTokenizer st = new StringTokenizer(br.readLine()); for (int i = 1; i <= N; i++) { a[i] = Integer.parseInt(st.nextToken()); } Stack<Integer> stk = new Stack<>(); stk.add(0); stk.add(1); int[] ans = new int[N + 1]; ans[1] = 0; for (int i = 2; i <= N; i++) { while (a[stk.peek()] >= a[i]) { stk.pop(); } // stk.peek()<a[i] // Esto existe porque a[0]=0 y a[i]>0 para todo i>0 ans[i] = stk.peek(); stk.push(i); } for (int i = 1; i <= N; i++) { System.out.print(ans[i] + " "); } } }
n = int(input()) nums = list(map(int, input().split())) ans = [] stack = [] # guarda (a_i, i) for idx, num in enumerate(nums): while stack and stack[-1][0] >= num: stack.pop() ans.append(0 if not stack else stack[-1][1] + 1) stack.append((num, idx)) print(*ans)

Problemas

HechoFuenteNombreDificultadTagsSolución
CSESAdvertisementFácilStackSolución
CFMike and FeetNormalStackSolución
CEOI2011 - BalloonsNormalStack, GeometrySolución
Baltic OI2012 - MobileNormalBinary Search, StackSolución
GoldModern Art 2NormalStackSolución
GoldDishwashingNormalStack, Binary SearchSolución
CSESMaximum Building INormalStackSolución
CEOI2020 - Fancy FenceNormalStack
CFRectanglesNormalStackSolución
GoldHILODifícilStack, Sorted Set, Linked ListSolución
CSESIncreasing Array QueriesDifícilStack, PURSSolución
CFSkyline PhotoDifícilStack, PURS, DP
IOI2004 - EmpodiaMuy difícilStackSolución
KilonovassdjMuy difícilStackSolución
CSESMaximum Building IIInsanoStackSolución
COI2015 - ŽaruljeInsanoStackSolución