스택 기반 배열 구현과 단조 창문 알고리즘

-1은 빈 리스트를 의미 head는 머리 노드의 인덱스 e[]는 특정 위치의 값, 인덱스는 노드의 위치 ne[]는 다음 포인터 idx는 현재까지 사용된 노드의 인덱스 단일 연결 리스트

단일 연결 리스트에서 idx는 삽입된 순서가 아니라, 현재까지 할당된 노드 번호를 나타냄


#include <iostream>

using namespace std;

const int N = 100010;

int head, e[N], ne[N], idx;

void init() {
    head = -1;
    idx = 0;
}

void add_to_head(int x) {
    e[idx] = x;
    ne[idx] = head;
    head = idx++;
}

void add(int k, int x) {
    e[idx] = x;
    ne[idx] = ne[k];
    ne[k] = idx++;
}

void remove(int k) {
    ne[k] = ne[ne[k]];
}

int main() {
    int m;
    cin >> m;
    init();

    while (m--) {
        char op;
        cin >> op;
        if (op == 'H') {
            int x;
            cin >> x;
            add_to_head(x);
        } else if (op == 'D') {
            int k;
            cin >> k;
            if (k == 0) head = ne[head];
            else remove(k - 1);
        } else {
            int k, x;
            cin >> k >> x;
            add(k - 1, x);
        }
    }

    for (int i = head; i != -1; i = ne[i]) 
        cout << e[i] << ' ';
    cout << endl;

    return 0;
}

이중 연결 리스트

#include <iostream>

using namespace std;

const int N = 100010;

int m, e[N], l[N], r[N], idx;

void insert(int k, int x) {
    e[idx] = x;
    l[idx] = k;
    r[idx] = r[k];
    l[r[k]] = idx;
    r[k] = idx++;
}

void remove(int k) {
    l[r[k]] = l[k];
    r[l[k]] = r[k];
}

int main() {
    cin >> m;
    r[0] = 1;
    l[1] = 0;
    idx = 2;

    while (m--) {
        string op;
        cin >> op;
        int k, x;
        if (op == "L") {
            cin >> x;
            insert(0, x);
        } else if (op == "R") {
            cin >> x;
            insert(l[1], x);
        } else if (op == "D") {
            cin >> k;
            remove(k + 1);
        } else if (op == "IL") {
            cin >> k >> x;
            insert(l[k + 1], x);
        } else {
            cin >> k >> x;
            insert(k + 1, x);
        }
    }

    for (int i = r[0]; i != 1; i = r[i])
        cout << e[i] << ' ';
    cout << endl;

    return 0;
}

스택을 이용한 수식 계산

#include <iostream>
#include <stack>
#include <unordered_map>
#include <cctype>

using namespace std;

stack<int> nums;
stack<char> ops;
unordered_map<char, int> priority{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};

void evaluate() {
    int b = nums.top(); nums.pop();
    int a = nums.top(); nums.pop();
    char op = ops.top(); ops.pop();
    int result;
    switch (op) {
        case '+': result = a + b; break;
        case '-': result = a - b; break;
        case '*': result = a * b; break;
        case '/': result = a / b; break;
    }
    nums.push(result);
}

int main() {
    string expression;
    cin >> expression;

    for (int i = 0; i < expression.size(); ++i) {
        char c = expression[i];
        if (isdigit(c)) {
            int num = 0;
            int j = i;
            while (j < expression.size() && isdigit(expression[j]))
                num = num * 10 + expression[j++] - '0';
            i = j - 1;
            nums.push(num);
        } else if (c == '(') {
            ops.push(c);
        } else if (c == ')') {
            while (ops.top() != '(')
                evaluate();
            ops.pop();
        } else {
            while (!ops.empty() && ops.top() != '(' && 
                   priority[ops.top()] >= priority[c])
                evaluate();
            ops.push(c);
        }
    }

    while (!ops.empty())
        evaluate();

    cout << nums.top() << endl;
    return 0;
}

단조 스택 문제 해결

#include <iostream>
using namespace std;

const int N = 100005;
int n, q[N], top;

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

    cin >> n;
    int x;
    for (int i = 0; i < n; ++i) {
        cin >> x;
        while (top > 0 && q[top] >= x)
            --top;
        if (top > 0)
            cout << q[top] << ' ';
        else
            cout << "-1 ";
        q[++top] = x;
    }
    return 0;
}

단조 큐를 활용한 최소값 찾기

#include <iostream>
using namespace std;

const int N = 1000010;

int a[N], q[N];

int main() {
    int n, k;
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; ++i)
        scanf("%d", &a[i]);

    int hh = 0, tt = -1;
    for (int i = 0; i < n; ++i) {
        if (hh <= tt && i - k + 1 > q[hh])
            ++hh;
        while (hh <= tt && a[q[tt]] >= a[i])
            --tt;
        q[++tt] = i;
        if (i >= k - 1)
            printf("%d ", a[q[hh]]);
    }
    puts("");

    hh = 0, tt = -1;
    for (int i = 0; i < n; ++i) {
        if (hh <= tt && i - k + 1 > q[hh])
            ++hh;
        while (hh <= tt && a[q[tt]] <= a[i])
            --tt;
        q[++tt] = i;
        if (i >= k - 1)
            printf("%d ", a[q[hh]]);
    }
    puts("");
    return 0;
}

해시 테이블 시뮬레이션

#include <cstring>
#include <iostream>
using namespace std;

const int N = 100003;

int h[N], e[N], ne[N], idx;

void insert(int x) {
    int k = (x % N + N) % N;
    e[idx] = x;
    ne[idx] = h[k];
    h[k] = idx++;
}

bool find(int x) {
    int k = (x % N + N) % N;
    for (int i = h[k]; i != -1; i = ne[i])
        if (e[i] == x)
            return true;
    return false;
}

int main() {
    int n;
    scanf("%d", &n);
    memset(h, -1, sizeof h);

    while (n--) {
        char op[2];
        int x;
        scanf("%s%d", op, &x);
        if (*op == 'I')
            insert(x);
        else
            puts(find(x) ? "Yes" : "No");
    }
    return 0;
}

또 다른 해시 테이블 구현 (오픈 어드레싱)

#include <cstring>
#include <iostream>
using namespace std;

const int N = 200003, INF = 0x3f3f3f3f;

int h[N];

int find(int x) {
    int t = (x % N + N) % N;
    while (h[t] != INF && h[t] != x) {
        t++;
        if (t == N) t = 0;
    }
    return t;
}

int main() {
    memset(h, 0x3f, sizeof h);
    int n;
    scanf("%d", &n);

    while (n--) {
        char op[2];
        int x;
        scanf("%s%d", op, &x);
        if (*op == 'I')
            h[find(x)] = x;
        else
            puts(h[find(x)] == INF ? "No" : "Yes");
    }
    return 0;
}

최장 증가 부분수열 구하기 (이진 탐색 기법)

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 100010;
int n, a[N], q[N];

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        scanf("%d", &a[i]);

    int len = 0;
    for (int i = 0; i < n; ++i) {
        int left = 0, right = len;
        while (left < right) {
            int mid = (left + right + 1) >> 1;
            if (q[mid] < a[i])
                left = mid;
            else
                right = mid - 1;
        }
        len = max(len, right + 1);
        q[right + 1] = a[i];
    }
    printf("%d\n", len);
    return 0;
}

그리디 기법을 활용한 최장 증가 부분수열

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> arr(n);
    for (int i = 0; i < n; ++i)
        cin >> arr[i];

    vector<int> stk;
    stk.push_back(arr[0]);

    for (int i = 1; i < n; ++i) {
        if (arr[i] > stk.back())
            stk.push_back(arr[i]);
        else
            *lower_bound(stk.begin(), stk.end(), arr[i]) = arr[i];
    }

    cout << stk.size() << endl;
    return 0;
}

태그: 스택 연결 리스트 해시 테이블 단조 스택 단조 큐

7월 17일 02:57에 게시됨