在平时的算法考试中,我们一般不采用指针链表的方式来模拟链表
我们采用数组来模拟链表
单链表:邻接表 -> 存储图和树
AcWing 826. 单链表
输入样例:
10 H 9 I 1 1 D 1 D 0 H 6 I 3 6 I 4 5 I 4 5 I 3 4 D 6
输出样例:
6 4 6 5
https://www.acwing.com/solution/content/126305/
插入操作
删除操作
#include <iostream> using namespace std; const int N = 100010; // head 表示头结点的下标 // e[i] 表示节点i的值 // ne[i] 表示节点i的next指针是多少 // idx 存储当前已经用到了哪个点 int head, e[N], ne[N], idx; // 初始化 void init() { head = -1; idx = 0; } // 将x插到头结点 void add_to_head(int x) { e[idx] = x, ne[idx] = head, head = idx ++ ; } // 将x插到下标是k的点后面 void add(int k, int x) { e[idx] = x, ne[idx] = ne[k], ne[k] = idx ++ ; } // 将下标是k的点后面的点删掉 void remove(int k) { ne[k] = ne[ne[k]]; } int main() { int m; cin >> m; init(); while (m -- ) { int k, x; 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; }
AcWing 827. 双链表
输入样例:
10 R 7 D 1 L 3 IL 2 10 D 3 IL 2 7 L 8 R 9 IL 4 7 IR 2 2
输出样例:
8 7 7 3 2 9
#include <iostream>
using namespace std;
const int N = 100010;
int m;
int e[N], l[N], r[N], idx;
// 在节点a的右边插入一个数x
void insert(int a, int x)
{
e[idx] = x;
l[idx] = a, r[idx] = r[a];
l[r[a]] = idx, r[a] = idx ++ ;
}
// 删除节点a
void remove(int a)
{
l[r[a]] = l[a];
r[l[a]] = r[a];
}
int main()
{
cin >> m;
// 0是左端点,1是右端点
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;
}
AcWing 829. 模拟队列
输入样例:
10 push 6 empty query pop empty push 3 push 4 pop query push 6
输出样例:
NO 6 YES 4
#include <iostream>
using namespace std;
const int N = 100010;
int m;
int q[N], hh, tt = -1;
int main()
{
cin >> m;
while (m -- )
{
string op;
int x;
cin >> op;
if (op == "push")
{
cin >> x;
q[ ++ tt] = x;
}
else if (op == "pop") hh ++ ;
else if (op == "empty") cout << (hh <= tt ? "NO" : "YES") << endl;
else cout << q[hh] << endl;
}
return 0;
}
AcWing 828. 模拟栈
输入样例:
10 push 5 query push 6 pop query pop empty push 4 query empty
输出样例:
5 5 YES 4 NO
#include <iostream>
using namespace std;
const int N = 100010;
int t;
int stk[N],tt = -1;
int main()
{
cin >> t;
while(t --)
{
string str;
cin >> str;
if(str == "push")
{
int x;
cin >> x;
stk[++ tt] = x;
}
else if(str == "pop") tt --;
else if(str == "query") cout << stk[tt] << endl;
else if(str == "empty")
{
if(tt < 0) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
return 0;
}
AcWing 830. 单调栈
输入样例:
5 3 4 2 7 5
输出样例:
-1 3 -1 2 2
单调栈算法,时间复杂度为。借助单调性处理问题的思想在于及时排除不可能的选项,保持策略集合的高度有效性和秩序性,从而为我们做出决策提供更多的条件和可能方法。
暴力做法
for(int i = 0; i < n; i ++ ) for(int j = i - 1; j >= 0; j -- ) if(a[i] > a[j]) { cout << a[j] << endl; break; }
利用单调栈的思想
假设 ,那么 在之后就不会作为答案出现,因为 总是作为更优的答案
#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; }
AcWing 154. 滑动窗口
输入样例:
8 3 1 3 -1 -3 5 3 6 7
输出样例:
-1 -3 -3 -3 3 3 3 3 5 5 6 7
#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;
}