1. 程式人生 > 實用技巧 >Acwing-----演算法基礎課之第二講(資料結構一)

Acwing-----演算法基礎課之第二講(資料結構一)

826. 單鏈表

使用陣列模擬連結串列,速度比較快;鄰接表,一般用來儲存樹和圖;

#include <iostream>
using namespace std;

const int N = 100010;

// head:頭節點的下標
// e:節點i的值
// ne:節點i的next指標
// idx:當前已經用到了哪個點
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, idx++;   
}

// 將x插入下標為k的節點後面
void add(int k, int x) {
    e[idx] = x, ne[idx] = ne[k], ne[k] = idx, idx++;
}

// 將下標是k的點後面的點刪掉
void remove(int k) {
    ne[k] = ne[ne[k]];
}

int main() {
    int m;
    cin >> m;
    init();
    while (m--) {
        int x, k;
        char op;
        cin >> op;
        if (op == 'H') {
            cin >> x;
            add_to_head(x);
        } else if (op == 'D') {
            cin >> k;
            if (!k) head = ne[head];
            else remove(k - 1);
        } else {
            cin >> k >> x;
            add(k - 1, x);
        }
    }
    
    for (int i = head; i != -1; i = ne[i]) cout << e[i] << ' ';
    cout << endl;
    return 0;
}                                              

827.雙鏈表

雙鏈表:一般用來優化某些問題;

#include <iostream>
using namespace std;

const int N = 100010;

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

void init() {
    // 0表示左端點,1表示右端點
    r[0] = 1, l[1] = 0;
    idx = 2;
}

// 在下標是k的點右邊插入x
void insert(int k, int x) {
    e[idx] = x;
    r[idx] = r[k];
    l[idx] = k;
    l[r[k]] = idx;
    r[k] = idx++;
}

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

int main() {
    init();
    cin >> m;
    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;
}

828.模擬棧

單調棧

#include <iostream>
using namespace std;

const int N = 100010;
int n;
int stk[N], tt;

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

154.滑動視窗

單調佇列

#include <iostream>
using namespace std;

const int N = 1000010;

int a[N], q[N], n, k;

int main() { 
    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;
}

831.KMP

next[i] = j表示p[1, j] = p[i - j + 1, i]

#include <iostream>

using namespace std;

const int N = 100010, M = 1000010;

int n, m;
int ne[N];
char s[M], p[N];

int main() {
    cin >> n >> p + 1 >> m >> s + 1;

    for (int i = 2, j = 0; i <= n; ++i) {
        while (j && p[i] != p[j + 1]) j = ne[j];
        if (p[i] == p[j + 1]) ++j;
        ne[i] = j;
    }

    for (int i = 1, j = 0; i <= m; ++i) {
        while (j && s[i] != p[j + 1]) j = ne[j];
        if (s[i] == p[j + 1]) ++j;
        if (j == n) {
            printf("%d ", i - n);
            j = ne[j];
        }
    }

    return 0;
}