学习课程内容
陈老板讲课相当高深,只有哈希听明白了一点
B站学习
C语言链表尾插
> void insertNodeByTrall(struct Node *List,int data) {
> struct Node *lastNode = endofList(List);
> struct Node *newNode = createNode(data);
> lastNode->next = newNode; } struct Node* endofList(struct Node *List) {
> while(List->next) List = List->next;
> return List; }
以及其他链表内容
bool InsertList(linklist *HeadNode,int LocateIndex,int InData)
> {
> int i=1;// 由于起始结点HeadNode是头结点,所以计数从1开始
>
> linklist *CurrentNode= (linklist *) HeadNode;
>
> //将CurrentNode指向待插入位置的前一个结点(index -1)
>
> while(CurrentNode&& i<LocateIndex-1)
>
> {
> CurrentNode= CurrentNode->next;
>
> i++;
>
> }
>
> linklist *NodeToInsert=(linklist*)malloc(sizeof(linklist));
>
> if(NodeToInsert == NULL)
>
> {
> printf("空间缓存不足");
>
> return ERROR;
>
> }
>
> NodeToInsert->Element= InData;
>
> NodeToInsert->next = CurrentNode->next;
>
> CurrentNode->next = NodeToInsert;
>
> return OK;
>
> } bool DeleteList(linklist * HeadNode,int index, int * DataToDel)
>
> {
> int i = 1;
>
> linklist *CurrentNode = HeadNode;
>
> linklist *NodeToDelete;
>
> //将CurrentNode指向待删除位置的前一个结点(index -1)
>
> while(CurrentNode&& i<index-1)
>
> {
> CurrentNode= CurrentNode->next;
>
> i++;
>
> }
>
> NodeToDelete = CurrentNode->next;
>
> *DataToDel =NodeToDelete->Element;
>
> CurrentNode->next= NodeToDelete->next;
>
> free(NodeToDelete);
>
> return OK;
>
> }
关于DFS的非队列尝试
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
int i,j,n,m1,m2,m3,k,step,s,a[1000000];
int find(int n,int k){
while(1){
if(n==k)
return step;printf("%d ",n);
step++;
if(n>1&&a[n-1]==0){
m1=n-1;
a[m1]=1;
}
if(n<=k&&a[n+1]==0){
m2=n+1;
a[m2]=1;
}
if(n<=k&&a[n*2]==0){
m3=m3*2;
a[m3]=1;
}find(m1,k);find(m2,k);find(m3,k);
if(a[n]==1)
return;
}
}
int main(){
scanf("%d %d",&n,&k);
memset(a,0,sizeof(a));
step=0;
a[n]=1;
s=find(n,k);
printf("%d",s);
return 0;
}
及关于该解法的试想
用三个函数进行递归检索
以下为引用课程大纲内容
图与搜索 状态空间和图(树) 树的前中后序遍历与层序遍历 dfs遍历图与求连通块 bfs遍历图与求最短路 数据结构 二叉树,二叉堆
二叉树的基本形态:空,仅左子树,仅右子树,有左右子树 二叉树的类别: 真二叉树:所有节点的度都要么为0,要么为2。
满二叉树(完美二叉树):所有节点的度要么为0,要么为2,且所有的叶子节点都在最后一层。
完全二叉树:叶子节点只会出现在最后2层,且最后一层的叶子节点都靠左对齐。 堆是完全二叉树 二叉树的基本性质 第 ii 层的节点数最大为
2^{i-1},i\geq12 i−1 ,i≥1 最大深度为 kk 层的二叉树最多有 2^k-12 k −1 个节点, k\geq
1k≥1 二叉树的几种遍历方法 先序遍历:根节点,左子树,右子树 中序遍历:左子树,根节点,右子树 后序遍历:左子树,右子树,根节点
层序遍历:从上到下,从左到右 二叉搜索树(二叉查找树) 静态查找问题可以使用二分法,使数据有序之后转化为了在树上的查找
O(log_2n)O(log 2 n) 对于动态查找,能否直接使用树形结构存储数据呢?
对任意树上的节点来说,它的值比所有左子树的大,比所有右子树的小。 删除节点 是叶子节点 只有一个子节点 有两个子节点
特殊情况会退化成链状,即斜二叉树
- 平衡二叉树,任意节点左右子节点高度差绝对值不超过 11 堆排序 小根堆:每个节点都小于他的左右子节点 完全二叉树的存储 两个基本操作:向下调整和向上调整 删除最小值操作为什么要与尾节点交换?和堆的储存方式相关 建堆 哈希表 普通的哈希表写法
作用:把一个大的值域空间映射到一个较小的空间。 [0,N][0,N],NN 取 10^510 5 ~ 10^610 6
例如,进行 nn 次操作,每次给出一个位于 [-109,109][−10 9 ,10 9 ]
的数,每次操作是将这个数插入集合或是判断是否已经在集合中存在 设计一个函数满足 h(x) \subset
[0,10^5]h(x)⊂[0,10 5 ],x\subset [-109,109]x⊂[−10 9 ,10 9 ]
,这个函数就被成为哈希函数 这个函数如何设计? 用于取模的数尽量选用质数,并且尽量离 22
的整次幂尽可能的远,可以证明这种情况哈希冲突的概率最小。 显然存在冲突(不同的 xx 得到的 f(x)f(x) 值相同),该怎么办? 拉链法
开一个 10^510 5 长度的数组,每一个“槽”拉一条链存储元素。
虽然每一个“槽”都拉了一条链,但是在平均情况下来看,这条链的长度可以看作是常数,在一般情况下,哈希表的时间复杂度都是 O(1)O(1) 的。
一般在哈希表的应用中,不需要考虑删除操作。 添加元素 开放寻址法 数组的长度需要为题目数据范围的2~3倍。 添加元素 查找元素 删除元素
字符串哈希方法(字符串前缀哈希法) 预处理出所有前缀的哈希,特别的 h[0]=0h[0]=0 将整个字符串看作是一个 pp
进制数,h(“ABCD”)=h((1234)_P)=h(1p3+2*p2+3p1+4*p0)=x%Qh(“ABCD”)=h((1234)
P )=h(1∗p 3 +2∗p 2 +3∗p 1 +4∗p 0 )=x%Q
通过这种方式将字符串转化成了一个数字,由于计算出的数很大,需要mod一个数 QQ。 不能有字母映射成 00 。
字符串哈希不考虑冲突情况,假定RP足够好不遇到冲突。 当 p=131p=131 或 p=13331p=13331 且 Q=2^{64}Q=2
64 时,基本上认为不会发生冲突。 为什么选用前缀哈希? 可以利用公式计算出子串的哈希值。(左边是高位,右边是低位) 并查集
每个点保存其父节点的信息 合并两个集合、查询两个元素是否在同一个集合 暴力:开数组保存元素属于的集合编号,查询 O(1)O(1),合并
O(n)O(n) 并查集:用树形结构保存集合,根节点编号作为集合编号,保存每个节点的父节点信息 Q:如何判断树根? Q:如何取得集合编号?
Q:如何合并两个集合? 此时的复杂度,查询 O(n)O(n),合并 O(1)O(1),如何优化(即降低树的高度)?
注:合并操作前需要先查询根节点信息,此处的“合并”未计算查询复杂度 加入路径压缩优化,查询
O(logn)O(logn),合并O(1)O(1) 加入按秩合并优化,查询 O(logn)O(logn),合并O(1)O(1)
加入上述两种优化,查询 O(\alpha(n))O(α(n)),合并O(1)O(1) 近似认为其查询操作的时间复杂度
O(\alpha(n)) = O(5) = O(1)O(α(n))=O(5)=O(1)- 由于阿克曼函数 f (n) = A(n, n)f(n)=A(n,n) 的增加速率非常快,因此其反函数 f^{−1} = \alphaf −1 =α 会以非常慢的速度增加。阿克曼反函数常用 αα 表示。因为 A(4, 4)A(4,4) 的数量级约等于\large
2{{2{{10^{{19729}}}}}}2 2 10 19729
,因此对于一般可能出现的数值 nn,α(n)α(n) 均小于 55。 字典树 最大异或对 树状数组前缀和
- 每个数组下标代表一个前缀, 值为前缀的和, 然后用数组元素间做减法算出某个区间的和.填例子
- 填题目
差分
- 保存相邻值的差.例子:每个数组下标代表一个前缀和, 上一个数组下标代表的前缀和 与 当前数组下标代表的前缀和 之差, 作为当前数组元素的值.(区间插气球问题)
- 填题目