来自北京大学NOIP金牌选手yxc的常用代码模板2——数据结构

本文介绍了C++中的队列、单调栈、KMP算法、Trie树、并查集、堆以及哈希技术,包括拉链法和开放寻址法,并提及了Java开发的学习资源,重点突出了算法在实际项目中的应用和面试中的重要性。
摘要由CSDN通过智能技术生成

q[hh];

// 判断队列是否为空

if (hh <= tt)

{

}

(2). 循环队列

// hh 表示队头,tt表示队尾的后一个位置

int q[N], hh = 0, tt = 0;

// 向队尾插入一个数

q[tt ++ ] = x;

if (tt == N) tt = 0;

// 从队头弹出一个数

hh ++ ;

if (hh == N) hh = 0;

// 队头的值

q[hh];

// 判断队列是否为空

if (hh != tt)

{

}

5.单调栈

常见模型:找出每个数左边离它最近的比它大/小的数

int tt = 0;

for (int i = 1; i <= n; i ++ )

{

while (tt && check(stk[tt], i)) tt – ;

stk[ ++ tt] = i;

}

6. 单调队列

常见模型:找出滑动窗口中的最大值/最小值

int hh = 0, tt = -1;

for (int i = 0; i < n; i ++ )

{

while (hh <= tt && check_out(q[hh])) hh ++ ; // 判断队头是否滑出窗口

while (hh <= tt && check(q[tt], i)) tt – ;

q[ ++ tt] = i;

}

7.KMP

// s[]是长文本,p[]是模式串,n是s的长度,m是p的长度

求模式串的Next数组:

for (int i = 2, j = 0; i <= m; 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 <= n; i ++ )

{

while (j && s[i] != p[j + 1]) j = ne[j];

if (s[i] == p[j + 1]) j ++ ;

if (j == m)

{

j = ne[j];

// 匹配成功后的逻辑

}

}

8.Trie树

int son[N][26], cnt[N], idx;

// 0号点既是根节点,又是空节点

// son[][]存储树中每个节点的子节点

// cnt[]存储以每个节点结尾的单词数量

// 插入一个字符串

void insert(char *str)

{

int p = 0;

for (int i = 0; str[i]; i ++ )

{

int u = str[i] - ‘a’;

if (!son[p][u]) son[p][u] = ++ idx;

p = son[p][u];

}

cnt[p] ++ ;

}

// 查询字符串出现的次数

int query(char *str)

{

int p = 0;

for (int i = 0; str[i]; i ++ )

{

int u = str[i] - ‘a’;

if (!son[p][u]) return 0;

p = son[p][u];

}

return cnt[p];

}

9.并查集

(1)朴素并查集:

int p[N]; //存储每个点的祖宗节点

// 返回x的祖宗节点

int find(int x)

{

if (p[x] != x) p[x] = find(p[x]);

return p[x];

}

// 初始化,假定节点编号是1~n

for (int i = 1; i <= n; i ++ ) p[i] = i;

// 合并a和b所在的两个集合:

p[find(a)] = find(b);

(2)维护size的并查集:

int p[N], size[N];

//p[]存储每个点的祖宗节点, size[]只有祖宗节点的有意义,表示祖宗节点所在集合中的点的数量

// 返回x的祖宗节点

int find(int x)

{

if (p[x] != x) p[x] = find(p[x]);

return p[x];

}

// 初始化,假定节点编号是1~n

for (int i = 1; i <= n; i ++ )

{

p[i] = i;

size[i] = 1;

}

// 合并a和b所在的两个集合:

size[find(b)] += size[find(a)];

p[find(a)] = find(b);

(3)维护到祖宗节点距离的并查集:

int p[N], d[N];

//p[]存储每个点的祖宗节点, d[x]存储x到p[x]的距离

// 返回x的祖宗节点

int find(int x)

{

if (p[x] != x)

{

int u = find(p[x]);

d[x] += d[p[x]];

p[x] = u;

}

return p[x];

}

// 初始化,假定节点编号是1~n

for (int i = 1; i <= n; i ++ )

{

p[i] = i;

d[i] = 0;

}

// 合并a和b所在的两个集合:

p[find(a)] = find(b);

d[find(a)] = distance; // 根据具体问题,初始化find(a)的偏移量

10.堆

// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1

// ph[k]存储第k个插入的点在堆中的位置

// hp[k]存储堆中下标是k的点是第几个插入的

int h[N], ph[N], hp[N], size;

// 交换两个点,及其映射关系

void heap_swap(int a, int b)

{

swap(ph[hp[a]],ph[hp[b]]);

swap(hp[a], hp[b]);

swap(h[a], h[b]);

}

void down(int u)

{

int t = u;

if (u * 2 <= size && h[u * 2] < h[t]) t = u * 2;

if (u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;

if (u != t)

{

heap_swap(u, t);

down(t);

}

}

void up(int u)

{

while (u / 2 && h[u] < h[u / 2])

{

heap_swap(u, u / 2);

u >>= 1;

}

}

// O(n)建堆

for (int i = n / 2; i; i – ) down(i);

11.一般哈希

(1) 拉链法

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;

}

(2) 开放寻址法

int h[N];

// 如果x在哈希表中,返回x的下标;如果x不在哈希表中,返回x应该插入的位置

int find(int x)

{

int t = (x % N + N) % N;

while (h[t] != null && h[t] != x)

{

t ++ ;

if (t == N) t = 0;

}

return t;

}

12.字符串哈希

核心思想:将字符串看成P进制数,P的经验值是13113331,取这两个值的冲突概率低

小技巧:取模的数用2^64,这样直接用unsigned long long存储,溢出的结果就是取模的结果

typedef unsigned long long ULL;

ULL h[N], p[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64

// 初始化

p[0] = 1;

for (int i = 1; i <= n; i ++ )

{

h[i] = h[i - 1] * P + str[i];

p[i] = p[i - 1] * P;

}

// 计算子串 str[l ~ r] 的哈希值

ULL get(int l, int r)

{

return h[r] - h[l - 1] * p[r - l + 1];

}

13.C++ STL简介

(1).vector, 变长数组,倍增的思想

size()返回元素个数

empty() 返回是否为空

clear()清空

front()/back()

push_back()/pop_back()

begin()/end()

[]

支持比较运算,按字典序

(2).pair<int, int>

first, 第一个元素

second, 第二个元素

支持比较运算,以first为第一关键字,以second为第二关键字(字典序)

(3). string,字符串

size()/length() 返回字符串长度

empty()

clear()

substr(起始下标,(子串长度)) 返回子串

c_str() 返回字符串所在字符数组的起始地址

(4). queue, 队列

size()

empty()

push() 向队尾插入一个元素

front()返回队头元素

back() 返回队尾元素

pop() 弹出队头元素

(5). priority_queue, 优先队列,默认是大根堆

size()

empty()

push() 插入一个元素

top()返回堆顶元素

pop()弹出堆顶元素

定义成小根堆的方式:priority_queue<int, vector<int>, greater<int>> q;

(6). stack, 栈

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。

以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考

一份还热乎的蚂蚁金服面经(已拿Offer)面试流程4轮技术面+1轮HR

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
g-wh9yexno-1713735698744)]

[外链图片转存中…(img-RsM4sWzN-1713735698745)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。

以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考

[外链图片转存中…(img-GOrEVNxo-1713735698745)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 28
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值