前言
重学算法第3天,希望能坚持打卡不间断,从基础课开始直到学完提高课。
预计时长三个月内,明天再来!肝就完了
2月15日,day03 打卡
今日已学完y总的
算法基础课-2.1-第二章 数据结构(一)
共7题,知识点如下
链表与邻接表:
单链表、双链表
栈与队列:
模拟栈、模拟队列
单调栈、单调队列 :滑动窗口(题目名)
KMP:KMP字符串
暂时先囫囵吞枣过一遍 ,以后开始大量刷题再慢慢把没完全理解的补一补
算法早学晚学都得学,不如现在直接学。
欠下的迟早要还
链表与邻接表
上述方式太慢,一般用在面试中,笔试不用
数组表示方式
单链表
模板
// head存储链表头,e[]存储节点的值,ne[]存储节点的next指针,idx表示当前用到了哪个节点
int head, e[N], ne[N], idx;
// 初始化
void init()
{
head = -1;
idx = 0;
}
// 在链表头插入一个数a
void insert(int a)
{
e[idx] = a, ne[idx] = head, head = idx ++ ;
}
// 将头结点删除,需要保证头结点存在
void remove()
{
head = ne[head];
}
AcWing 826. 单链表
思路:
- 将x插入到头结点
先让红色指向head里面存的这个值,再让head指向红色点
- 将x插到下标是k的点后面
- 将下标是k的点后面的点删掉
样例操作后的结果
#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) {
// head = idx, idx++ 可合并
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 ++;
}
// 将下标是k的点后面的点删掉
int 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]; // 删除头结点,直接指向下一个点
remove(k - 1); // 第k个点,下标k-1
} else {
cin >> k >> x;
add(k - 1, x);
}
}
for (int i = head; i != - 1; i = ne[i]) // i从头结点开始,没遍历到空节点,每次i往后走一步
cout << e[i] << ' '; // 输出i对应的值
cout << endl;
return 0;
}
算法题不需要考虑内存泄露的问题,做项目才需要
双链表
模板
// e[]表示节点的值,l[]表示节点的左指针,r[]表示节点的右指针,idx表示当前用到了哪个节点
int e[N], l[N], r[N], idx;
// 初始化
void init()
{
//0是左端点,1是右端点
r[0] = 1, l[1] = 0;
idx = 2;
}
// 在节点a的右边插入一个数x
void