Khoá học C++ nâng cao
Bài học: Ngăn Xếp, Hàng Đợi & Deque
🏆 +100 XP tiềm năng Thoát

Ngăn Xếp, Hàng Đợi & Deque

2 khối nội dung 45 phút học tập MỞ BẢNG TRẮNG

Ngăn Xếp, Hàng Đợi & Deque

Nội dung bài học

1. Khái niệm & bản chất của cấu trúc dữ liệu tuyến tính đơn điệu

Ngăn xếp (Stack - LIFO) và Hàng đợi (Queue - FIFO) là hai cấu trúc dữ liệu cơ sở có thời gian thêm và xóa ở đầu/cuối trong $\mathcal{O}(1)$.

Ở Level 2, ta nâng cấp lên Ngăn xếp đơn điệu (Monotonic Stack)Hàng đợi hai đầu đơn điệu (Monotonic Deque) — hai công cụ tối ưu hóa cực mạnh giúp giải quyết các bài toán tìm kiếm phần tử lớn hơn/nhỏ hơn gần nhất và duy trì $\min/\max$ trên cửa sổ trượt trong thời gian tuyến tính $\mathcal{O}(N)$ (thay vì $\mathcal{O}(N^2)$ hoặc $\mathcal{O}(N \log K)$).


Ngăn xếp đơn điệu Monotonic Stack

2. Ngăn xếp đơn điệu

2.1. Bài toán: Tìm phần tử lớn hơn gần nhất bên phải (Next Greater Element — NGE)

Cho mảng $A = [A_1, A_2, \dots, A_N]$. Với mỗi $i$, tìm chỉ số $j > i$ nhỏ nhất sao cho $A_j > A_i$.

  • Ý tưởng Monotonic Stack: Duyệt mảng từ phải sang trái (hoặc từ trái sang phải), duy trì một ngăn xếp chứa các phần tử giảm dần từ đáy lên đỉnh:

  • Khi xét phần tử $A_i$, loại bỏ tất cả các phần tử trên đỉnh ngăn xếp mà $\le A_i$ (vì chúng nhỏ hơn $A_i$ và nằm xa hơn, không bao giờ có thể là NGE cho các phần tử đứng trước $i$).

  • Phần tử còn lại trên đỉnh ngăn xếp chính là NGE của $A_i$.
  • Đẩy $A_i$ vào ngăn xếp.
vector<int> next_greater_element(const vector<int> &a) {
    int n = a.size();
    vector<int> res(n, -1);
    stack<int> st; // Lưu chỉ số

    for (int i = n - 1; i >= 0; --i) {
        while (!st.empty() && a[st.top()] <= a[i]) {
            st.pop();
        }
        if (!st.empty()) res[i] = st.top();
        st.push(i);
    }
    return res;
}

Chứng minh độ phức tạp $\mathcal{O}(N)$: Mỗi phần tử chỉ được đẩy vào ngăn xếp đúng 1 lần và lấy ra khỏi ngăn xếp tối đa 1 lần $\implies$ Tổng số thao tác push/pop là $2N$.


3. Hàng đợi hai đầu đơn điệu (Monotonic Deque)

3.1. Bài toán: Tìm giá trị nhỏ nhất trên mọi cửa sổ trượt độ dài $K$ (Sliding Window Minimum)

Cho mảng $A$ và kích thước cửa sổ $K$. Tìm $\min$ của mỗi cửa sổ con liên tiếp $K$ phần tử.

  • Cơ chế Monotonic Deque: Duy trì một deque<int> lưu chỉ số sao cho giá trị tương ứng trong mảng luôn tăng dần từ đầu đến cuối:
  1. Loại bỏ phần tử ngoài cửa sổ: Nếu chỉ số ở đầu deque $\le i - K$, đẩy ra (pop_front).
  2. Duy trì tính đơn điệu: Trong khi đuôi deque có giá trị $\ge A_i$, đẩy ra (pop_back) vì chúng vừa lớn hơn vừa già hơn $A_i$.
  3. Thêm $i$ vào đuôi: push_back(i).
  4. Phần tử ở đầu deque deque.front() luôn là $\min$ của cửa sổ hiện tại.
vector<int> sliding_window_min(const vector<int> &a, int k) {
    int n = a.size();
    vector<int> res;
    deque<int> dq;

    for (int i = 0; i < n; ++i) {
        if (!dq.empty() && dq.front() <= i - k) dq.pop_front();
        while (!dq.empty() && a[dq.back()] >= a[i]) dq.pop_back();
        dq.push_back(i);
        if (i >= k - 1) res.push_back(a[dq.front()]);
    }
    return res;
}

4. Mẫu cài đặt chuẩn thi đấu: Diện tích hình chữ nhật lớn nhất trong biểu đồ cột (Histogram)

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    if (!(cin >> n)) return 0;

    vector<long long> h(n);
    for (int i = 0; i < n; ++i) cin >> h[i];

    stack<int> st;
    long long max_area = 0;

    for (int i = 0; i <= n; ++i) {
        long long cur_h = (i == n ? 0 : h[i]);
        while (!st.empty() && cur_h < h[st.top()]) {
            long long height = h[st.top()];
            st.pop();
            long long width = (st.empty() ? i : (i - st.top() - 1));
            max_area = max(max_area, height * width);
        }
        st.push(i);
    }

    cout << max_area << "\n";
    return 0;
}

5. Ranh giới áp dụng

Kỹ Thuật Mục Đích Độ Phức Tạp Thời Gian Độ Phức Tạp Không Gian
Monotonic Stack Tìm phần tử lớn hơn/nhỏ hơn gần nhất (NGE/PLE), Diện tích Histogram $\mathcal{O}(N)$ $\mathcal{O}(N)$
Monotonic Deque Tìm $\min/\max$ trên cửa sổ trượt độ dài cố định $K$ $\mathcal{O}(N)$ $\mathcal{O}(K)$
Multiset / Priority Queue Duy trì $\min/\max$ khi cửa sổ co giãn tùy ý có xóa phần tử $\mathcal{O}(N \log K)$ $\mathcal{O}(K)$

1
A
B
C
D
2
A
B
C
D

Bài tập lập trình vận dụng

22 Bài tập thực hành

Nhấn vào nút "Làm bài" bên dưới để mở giao diện làm bài trực tuyến (Online Judge) và thực hiện viết mã nguồn cho bài tập này.

Phần tử lớn hơn gần nhất (nge)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Giá trị nhỏ nhất trên cửa sổ trượt k
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Kiểm tra dãy ngoặc đúng nhiều loại
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tầm nhìn xa của các tòa nhà cao tầng
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Hình chữ nhật lớn nhất dưới biểu đồ cột (histogram)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Ma trận toàn số 1 lớn nhất (maximal rectangle 2d)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tổng hiệu cực đại và cực tiểu mọi đoạn con
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tối ưu hóa quy hoạch động bằng monotonic deque
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Hứng nước mưa đa chiều (trapping rain water)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đánh giá biểu thức số học trung tố (shunting-yard)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Phần tử lớn hơn gần nhất trên mảng xoay vòng
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Xóa k chữ số để được số nhỏ nhất
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tổng giá trị min mọi đoạn con nhân độ dài
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đua xe trong mê cung đổi hướng ít nhất (0-1 BFS)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Cắt băng rôn quảng cáo tối ưu bằng 2 deque
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Khôi phục cây khảo sát tầm nhìn đa hướng
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Hinh chu nhat lon nhat bieu do cot
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Hinh chu nhat toan so 1 lon nhat 2d
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tong min tat ca doan con
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Deque Sliding Window maximum
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Stack danh gia bieu thuc so hoc
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tam nhin toa nha hai chieu
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài