算法与数据结构面试题
算法与数据结构面试题
加油!
考查数据结构本身
什么是数据结构
简单地说,数据结构是以某种特定的布局方式存储数据的容器。这种“布局方式”决定了数据结构对于某些操作是高效的,而对于其他操作则是低效的。首先我们需要理解各种数据结构,才能在处理实际问题时选取最合适的数据结构。
为什么要使用数据结构
数据是计算机科学当中最关键的实体,而数据结构则可以将数据以某种组织形式存储,因此,数据结构的价值不言而喻。
无论你以何种方式解决何种问题,你都需要处理数据——无论是涉及员工薪水、股票价格、购物清单,还是只是简单的电话簿问题。
数据需要根据不同的场景,按照特定的格式进行存储。有很多数据结构能够满足以不同格式存储数据的需求。
常见的数据结构
首先列出一些最常见的数据结构,我们将逐一说明:
-
数组
- 数组是最简单、也是使用最广泛的数据结构。栈、队列等其他数据结构均由数组演变而来。
- 每个数据元素都关联一个正数值,我们称之为索引,它表明数组中每个元素所在的位置。大部分语言将初始索引定义为零。
- 以下是数组的两种类型:
- 一维数组
- 多维数组(数组的数组)
- 数组的基本操作:
- Insert——在指定索引位置插入一个元素
- Get——返回指定索引位置的元素
- Delete——删除指定索引位置的元素
- Size——得到数组所有元素的数量
-
栈
- 后进先出
- 栈的基本操作
- Push——在顶部插入一个元素
- Pop——返回并移除栈顶元素
- isEmpty——如果栈为空,则返回true
- Top——返回顶部元素,但并不移除它
-
队列
- 与栈相似,队列是另一种顺序存储元素的线性数据结构。栈与队列的最大差别在于栈是LIFO(后进先出),而队列是FIFO,即先进先出。
- 队列的基本操作
- Enqueue() —— 在队列尾部插入元素
- Dequeue() ——移除队列头部的元素
- isEmpty()——如果队列为空,则返回true
- Top() ——返回队列的第一个元素
-
链表
- 链表是另一个重要的线性数据结构,乍一看可能有点像数组,但在内存分配、内部结构以及数据插入和删除的基本操作方面均有所不同。
- 链表就像一个节点链,其中每个节点包含着数据和指向后续节点的指针。 链表还包含一个头指针,它指向链表的第一个元素,但当列表为空时,它指向null或无具体内容。
- 链表一般用于实现文件系统、哈希表和邻接表。
- 链表包括以下类型:
- 单链表(单向)
- 双向链表(双向)
- 链表的基本操作
- InsertAtEnd - 在链表的末尾插入指定元素
- InsertAtHead - 在链接列表的开头/头部插入指定元素
- Delete - 从链接列表中删除指定元素
- DeleteAtHead - 删除链接列表的第一个元素
- Search - 从链表中返回指定元素
- isEmpty - 如果链表为空,则返回true
-
树
- 树形结构是一种层级式的数据结构,由顶点(节点)和连接它们的边组成。 树类似于图,但区分树和图的重要特征是树中不存在环路。
- 树形结构被广泛应用于人工智能和复杂算法,它可以提供解决问题的有效存储机制。
- 树的基本术语
- Root - 根节点
- Parent - 父节点
- Child - 子节点
- Leaf - 叶子节点
- Sibling - 兄弟节点
- 树型结构的基本类型
- N元树
- 平衡树
- 二叉树
- 二叉搜索树
- AVL树
- 红黑树
- 2-3树
- 其中,二叉树和二叉搜索树是最常用的树
-
图
- 图是一组以网络形式相互连接的节点。节点也称为顶点。 一对节点(x,y)称为边(edge),表示顶点x连接到顶点y。边可以包含权重/成本,显示从顶点x到y所需的成本。
- 图的类型
- 无向图
- 有向图
- 在程序语言中,图可以用两种形式表示:
- 邻接矩阵
- 邻接表
- 常见图遍历算法
- 广度优先搜索
- 深度优先搜索
-
字典树(Trie)(这是一种高效的树形结构,但值得单独说明)
- 字典树,也称为“前缀树”,是一种特殊的树状数据结构,对于解决字符串相关问题非常有效。它能够提供快速检索,主要用于搜索字典中的单词,在搜索引擎中自动提供建议,甚至被用于IP的路由。
-
散列表(哈希表)
- 哈希法(Hashing)是一个用于唯一标识对象并将每个对象存储在一些预先计算的唯一索引(称为“键(key)”)中的过程。因此,对象以键值对的形式存储,这些键值对的集合被称为“字典”。可以使用键搜索每个对象。基于哈希法有很多不同的数据结构,但最常用的数据结构是哈希表。
- 哈希表通常使用数组实现。
- 散列数据结构的性能取决于以下三个因素:
- 哈希函数
- 哈希表的大小
- 碰撞处理方法
!> 简单谈谈常见的数据结构
a、数组:顺序存储,随机访问 链表:链表存储,顺序访问
b、栈,分为栈顶和栈底,遵循先进后出原则
c、队列 ,一个线性表,像排队一样,受约束控制,遵循先进先出原则
d、树:二叉树、平衡二叉树、大顶堆,小顶堆等
e、图:最短路径,关键路径
顺序结构和链式结构的区别?
顺序结构是指内存连续的存储单元进行存储,而链式结构是指 内存不连续的结构,通过一个节点指向另外一个节点的地址。
数据结构的三要素
- 逻辑结构:探讨数据元素之间的逻辑关系
- 集合:各个元素同属于一个集合,别无其他关系
- 线性结构:
- 数据元素之间是一对一的关系
- 除了第一个元素,所有元素都有唯一前驱
- 除了最后一个元素,所有元素都有唯一后继
- 树形结构:数据元素之间是一对多的关系
- 图状结构(网状结构):数据元素之间是多对多的关系
- 物理结构(存储结构):探讨如何用计算机表示数据元素的逻辑关系?
- 顺序存储
- 链式存储
- 索引存储
- 散列存储
- 根据元素的关键字直接计算出该元素的存储地址,又称为哈希(Hash)存储
- 数据的运算
复杂度是什么 ⭐
复杂度包括时间复杂度和空间复杂度,用来评价一个算法的好坏。
考查线性表
线性表查找有那几类?
直接查找和有序表的二分查找。
单链表和顺序表的对比
(1)存储方式:顺序表用一组连续的存储单元依次存储线性表的数据元素;而单链表用一组任意的存储单元存放线性表的数据元素。
(2)时间性能:采用循序存储结构时查找的时间复杂度为O(1),插入和删除需要移动平均一半的数据元素,时间复杂度为O(n)。采用单链表存储结构的查找时间复杂度为O(n),插入和删除不需要移动元素,时间复杂度仅为O(1)。
(3)空间性能:采用顺序存储结构时需要预先分配存储空间,分配空间过大会造成浪费,过小会造成问题。采用单链表存储结构时,可根据需要进行临时分配,不需要估计问题的规模大小,只要内存够就可以分配,还可以用于一些特殊情况,如一元多项的表示。
顺序结构和链式结构的区别 ⭐
顺序结构是指内存连续的存储单元进行存储,而链式结构是指内存不连续的结构,通过一个节点指向另外一个节点的地址。
考查数组
寻找数组中第二小的元素
找到数组中第一个不重复出现的整数
合并两个有序数组
重新排列数组中的正值和负值
数组和链表的区别 ⭐
从逻辑结构上来看,数组必须实现定于固定的长度,不能适应数据动态增减的情况,即数组的大小一旦定义就不能改变。当数据增加是,可能超过原先定义的元素的个数;当数据减少时,造成内存浪费;链表动态进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。
从内存存储的角度看;数组从栈中分配空间(用new则在堆上创建),对程序员方便快速,但是自由度小;链表从堆中分配空间,自由度大但是申请管理比较麻烦。
从访问方式类看,数组在内存中是连续的存储,因此可以利用下标索引进行访问;链表是链式存储结构,在访问元素时候只能够通过线性方式由前到后顺序的访问,所以访问效率比数组要低。
考查栈
使用栈计算后缀表达式
对栈的元素进行排序
判断表达式是否括号平衡
栈和队列的区别 ⭐
栈是先进后出的特殊线性表,队列是先进先出的线性表。
- 栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的。
- 栈是先进后出的特殊线性表,队列是先进先出的线性表
- 栈只允许在表尾一端进行插入和删除,队列只允许在表尾一端进行插入,在表头一端进行删除。
换种方式询问:栈和队列的不同,以及他们的相应存储方式。(这个后面一问有点难度,要回答在不同方式下的存储)
栈的存储方式 ⭐
栈也有两种存储方法:一是顺序栈;二是链式栈。栈的顺序存储结构是利用一组地址连续的存储单元依次存储自栈底到栈顶的数据元素,同时附设指针 top 指示栈顶元素的位置。由于栈的操作是线性表操作的特例,相对而言,链式栈的操作更易于实现。
栈和堆的区别 ⭐
栈区:由编辑器自动分配释放,存放函数的参数值,局部变量的值等(基本类型值)。
堆区:由程序员分配释放,若程序员不释放,程序结束时可能有 OS 回收(引用类型值)。
栈(数据结构):一种先进后出的数据结构。
堆(数据结构):堆可以被看成是一棵树,如:堆排序。
用两个栈实现一个队列的功能
算法思路:(时间复杂度为 O(1))
设 2 个栈为 A、B,一开始均为空
入队:将新元素 push 入栈 A
出队:
(1)判断栈 B 是否为空
(2)如果不为空,则将栈 A 中所有元素依次 pop 出并 push 给栈 B
(3)将栈 B 的栈顶元素 pop 出
Heap 和 Stack 的区别
Heap 是堆,Stack 是栈
1 Stack 的空间由操作系统自动分配和释放,Heap 上的空间手动分配和释放
2 Stack 空间有限,Heap 是很大的自由存储区
3 C 中的 malloc 函数分配的内存空间即在堆上,C++ 中对应的是 new 操作符
考查队列
使用队列表示栈
对队列的前k个元素倒序
使用队列生成从1到n的二进制数
队列的存储方式 ⭐
队列也有两种存储方法:一是顺序队列;二是链式队列,拿链式结构来实现队列,只要将头节点当作队头,尾结点当作队尾,入队时尾节点后移(next),出队时头节点后移(next)
考查链表
头节点的作用是什么 ⭐
头节点是指向初始地址的一个节点,它本身数据段没有内容,通过它可以标识这个链表。
反转链表
检测链表中的循环
返回链表倒数第N个节点
删除链表中的重复项
考查图
图的存储 ⭐
邻接矩阵和邻接表,是多对多的关系,分为有向图和无向图。
实现广度和深度优先搜索
深度优先和广度优先的对比
深度优先搜索(回溯法)
算法思路
深度优先搜索(DFS,Depth-First Search)是搜索的手段之一
它从某个状态开始,不断地转移状态直到无法转移,然后回退到前一步状态,继续转移到其他状态,如此不断重复,直到找到最终的解.根据深度优先搜索的特点,采用递归函数(隐式地利用了栈进行计算)实现比较简单.
算法效率
深度优先搜索从最开始的状态出发,遍历所有可以到达的状态.由此可以对所有的状态进行操作,或列举出所有的状态.作为搜索算法的一种,DFS对于寻找一个解的NP(包括NPC)问题作用很大.
但是,搜索算法毕竟是时间复杂度是O(n!)的阶乘级算法,它的效率比较低,在数据规模变大时,这种算法就显得力不从心了.关于深度优先搜索的效率问题,有多种解决方法.最具有通用性的是**剪枝(prunning),**也就是去除没有用的搜索分支.有可行性剪枝和最优性剪枝两种.此外,对于很多问题,可以把搜索与动态规划(DP,dynamic programming)、完备匹配(匈牙利算法)等高效算法结合.
2.宽度优先搜索(分支限界法)
算法思路
宽度优先搜索(BFS,Breadth-First Search)也是搜索的手段之一.他与深度优先搜索类似,从某个状态出发搜索所有可以到达的状态.根据宽度优先搜索的特点,采用队列实现比较简单.
算法效率
与深度优先不同之处在与搜索的顺序,宽度优先搜索总是先搜索距离初始状态近的状态.也就是说,它是按照开始状态->只需1次转移就可以到达的所有状态->只需2次转移就可以到达的所有状态->…这样的顺序进行搜索.对于同一个状态,宽度优先搜索只经过一次,因此复杂度为
O(状态数*转移的方式).很容易地用来求最短路径、最少操作之类问题的答案.
广度搜索的判断重复如果直接判断十分耗时,我们一般借助哈希表来优化时间复杂度.
3.Death-Breadth总结
宽度优先搜索与深度优先搜索一样,都会生成所有能够遍历到的状态,因此需要对所有状态进行处理时使用宽度优先也是可以的.但是递归函数可以很简短地编写,而且状态的管理也更简单,所以大多数情况下还是用深度优先搜索实现.反之,在求取最短路时深度优先搜索需要反复经过同样的状态,所以还是使用宽度优先搜索比较好.
宽度优先搜索会把状态逐个加入队列,因此通常需要与状态数成正比的内存空间.反之,深度优先搜索是与最大的递归深度成正比的.一般与状态数相比,递归的深度并不会太大,所以可以认为深度优先搜索更加节省内存.
检查图是否为树
计算图的边数
找到两个顶点之间的最短路径
邻接矩阵与邻接表
邻接矩阵表示法:在一个一维数组中存储所有的点,在一个二维数组中存储顶点之间的边的权值
邻接表表示法:图中顶点用一个一维数组存储,图中每个顶点vi的所有邻接点构成单链表
对比
1)在邻接矩阵表示中,无向图的邻接矩阵是对称的。矩阵中第 i 行或 第 i 列有效元素个数之和就是顶点的度。
在有向图中 第 i 行有效元素个数之和是顶点的出度,第 i 列有效元素个数之和是顶点的入度。
2)在邻接表的表示中,无向图的同一条边在邻接表中存储的两次。如果想要知道顶点的度,只需要求出所对应链表的结点个数即可。
有向图中每条边在邻接表中只出现一次,求顶点的出度只需要遍历所对应链表即可。求入度则需要遍历其他顶点的链表。
3)邻接矩阵与邻接表优缺点:
邻接矩阵的优点是可以快速判断两个顶点之间是否存在边,可以快速添加边或者删除边。而其缺点是如果顶点之间的边比较少,会比较浪费空间。因为是一个 n∗n 的矩阵。
而邻接表的优点是节省空间,只存储实际存在的边。其缺点是关注顶点的度时,就可能需要遍历一个链表。
考查树
介绍以下各种树 ⭐
树,二叉树:有左右子树的区分和度不超过2.
二叉排序树:左子树均小于根,根均小于右节点。。
线索二叉树:设置两个标识标记左右指针指向的是孩子还是前躯节点。
平衡二叉树:左右子树高度差绝对值小于等于1。
哈夫曼树:压缩用的。权值大小排列。
完全二叉树:只能从右边为空。
度为 2 的树和二叉树的区别 ⭐
二叉树有左右子树的定义。
树的存储结构 ⭐
孩子链存储结构和双亲存储结构。
树的遍历 ⭐
先序中序后序三种。递归实现。
求二叉树的高度
在二叉搜索树中查找第k个最大值
查找与根节点距离k的节点
在二叉树中查找给定节点的祖先节点
开销量,为何使用二叉树
在计算机科学中,二叉树是每个结点最多有两个子树的有序树。通常根的子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用作二叉查找树和二叉堆或是二叉排序树。二叉树的每个结点至多只有二棵子树(不存在出度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。
文件系统和数据库系统一般都采用树(特别是B树)的数据结构数据,主要为排序和检索的效率。二叉树是一种最基本最典型的排序树,用于教学和研究树的特性,本身很少在实际中进行应用,因为缺点太明显了(看看教科书怎么说的)。就像冒泡排序一样,虽然因为效率问题并不实用,单不失一种教学例子的好手段。
B树和B+树的区别,以一个m阶树为例
关键字的数量不同:B+树中分支结点有m个关键字,其叶子结点也有m个,其关键字只是起到了一个索引的作用,但是B树虽然也有m个子结点,但是其只拥有m-1个关键字。
存储的位置不同:B+树中的数据都存储在叶子结点上,也就是其所有叶子结点的数据组合起来就是完整的数据,但是B树的数据存储在每一个结点中,并不仅仅存储在叶子结点上。
分支结点的构造不同:B+树的分支结点仅仅存储着关键字信息和儿子的指针(这里的指针指的是磁盘块的偏移量),也就是说内部结点仅仅包含着索引信息。
查询不同:B树在找到具体的数值以后,则结束,而B+树则需要通过索引找到叶子结点中的数据才结束,也就是说B+树的搜索过程中走了一条从根结点到叶子结点的路径。
请比较最小生成树的算法(普里姆算法,克鲁斯卡尔算法)的异同
最小生成树:
最小生成树来自于无向网。
无向图在边上加上权值就成了无向网。
一个无向图可以有多种不同姿态连接的生成树。
最小生成树就是–各边上权值之和最小的生成树。
普里姆算法(Prim)和克鲁斯卡尔(Kruskal)算法
普里姆算法的基本思想:(简单的说就是一直加点)
取图中任意一个顶点 v 作为生成树的根,之后往生成树上添加新的顶点 w。添加顶点w的条件为:w 和已在生成树上的顶点v 之间必定存在一条边,并且该边的权值在所有连通顶点 v 和 w 之间的边中取值最小。之后继续往生成树上添加顶点,直至生成树上含有 n-1 个顶点为止。
克鲁斯卡尔算法的基本思想:(简单的说就是找不围成圈的最小的边)
考虑问题的出发点: 为使生成树上边的权值之和达到最小,则应使生成树中每一条边的权值尽可能地小。
具体做法: 先构造一个只含 n 个顶点的子图 SG,然后从权值最小的边开始,若它的添加不使SG 中产生回路,则在 SG 上加上这条边,如此重复,直至加上 n-1 条边为止。
什么时候最小生成树唯一?
当带权连通图的任意一个环中所包含的权值均不相同
Dijkstra 算法与 Prim 算法的区别
1.prim算法过程:
prim算法是最小生成树算法,它运用的是贪心原理,设置两个点集合,一个集合为要求的生成树的点集合A,另一个集合为未加入生成树的点B。
它的具体实现过程是:
(1):所有的点都在集合B中,A集合为空。(memset(visited,0,sizeof(visited))
(2):任意以一个点为开始,把这个初始点加入集合A中,从集合B中减去这个点(visited[1]=1)。寻找与它相邻的点中路径最短的点,如后把这个点也加入集合A中,从集合B中减去这个点(visited[pos]=1)。
(3):更新未被访问的节点的dist[]值。
(4):重复上述过程。一直到所有的点都在A集合中结束。
2.dijkstra算法过程:
(1)初始时,S只包含源点v,即S=v。U包含除v外的其他顶点,U中顶点u距离为边上的权(若v与u有边)或(若u不是v的出边邻接点)。
(2)从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
(3)以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u(u U)的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
(4)重复步骤(2)和(3)直到所有顶点都包含在S中。
3.小总结
1:Prim是计算最小生成树的算法,Dijkstra是计算最短路径的算法,
2、都是使用贪婪和线性规划,每一步都是选择权值/花费最小的边。
贪婪:一个局部最有解也是全局最优解;
线性规划:主问题包含n个子问题,而且其中有重叠的子问题。
什么是平衡二叉树
左右子树都是平衡二叉树,且左右子树的深度差值的绝对值不大于 1
考查字典树
计算字典树中的总单词数
打印存储在字典树中的所有单词
使用字典树对数组的元素进行排序
使用字典树从字典中形成单词
构建T9字典(字典树+ DFS )
考查算法
请说出以下算法的时间复杂度
冒泡排序法 插入排序法 堆排序法 二叉树排序法
O(n^2) O(n^2) O(nlog2n) 最差 O(n2) 平均 O(nlog2n)
快速排序法 希尔排序法
最差 O(n^2) 平均 O(nlog2n) O(nlog n) 不稳定
排序算法有哪些 ⭐
或者问:C语言总共有多少种排序法
- 排序算法有很多,每种算法有不同的时间和空间复杂度,效率也有差别,那么针对使用上也有不同的场合。原则上说,数据结构是一门领域,跟语言没有绝对的联系,很多时候同样的算法可以用很多种语言实现。
- 下面罗列一些常见的算法:插入排序,冒泡排序,选择排序,快速排序,堆排序,归并排序,基数排序,希尔排序等。
插入排序有直接插入和折半插入。都是在有序表里插入进去的。
交换排序:冒泡,快速:以一个数字划分两个区域,然后分别对两个区域继续划分,直到区间为一。注意快排是不稳定。
选择排序:简单的选择排序,堆排序
归并排序:将两个有序表归并到一个有序表。将两个有序表放到一起进行各个比较,比较完之后放回原来数组内。
时间复杂度:
(1)平方阶(O(n2))排序
各类简单排序:直接插入、直接选择和冒泡排序;
(2)线性对数阶(O(nlog2n))排序
快速排序、堆排序和归并排序;
(3)O(n1+§))排序,§是介于0和1之间的常数。
希尔排序
(4)线性阶(O(n))排序
基数排序,此外还有桶、箱排序。
稳定性:
排序算法的稳定性:若待排序的序列中,存在多个具有相同关键字的记录,经过排序,这些记录的相对次序保持不变,则称该算法是稳定的;若经排序后,记录的相对次序发生了改变,则称该算法是不稳定的。
稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序
不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序
什么是稳定的算法 ⭐
不乱动已经排序好的数字,这样算法稳定一些。
选择排序算法的准则
一般而言,需要考虑的因素有以下四点:
设待排序元素的个数为n.
**1)**当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序序。
**2)**当n较大,内存空间允许,且要求稳定性:归并排序
**3)**当n较小,可采用直接插入或直接选择排序。
直接插入排序:当元素分布有序,直接插入排序将大大减少比较次数和移动记录的次数。
直接选择排序 :元素分布有序,如果不要求稳定性,选择直接选择排序
**5)**一般不使用或不直接使用传统的冒泡排序。
6**)**基数排序
它是一种稳定的排序算法,但有一定的局限性:
1、关键字可分解。
2、记录的关键字位数较少,如果密集更好
3、如果是数字时,最好是无符号的
简述快速排序过程
1)选择一个基准元素,通常选择第一个元素或者最后一个元素,
2)通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的元素值比基准值大。
3)此时基准元素在其排好序后的正确位置
4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
快速排序的改进
只对长度大于k的子序列递归调用快速排序,让原序列基本有序,然后再对整个基本有序序列用插入排序算法排序。实践证明,改进后的算法时间复杂度有所降低,且当k取值为 8 左右时,改进算法的性能最佳。
选择基准元的方式
对于分治算法,当每次划分时,算法若都能分成两个等长的子序列时,那么分治算法效率会达到最大。也就是说,基准的选择是很重要的。选择基准的方式决定了两个分割后两个子序列的长度,进而对整个算法的效率产生决定性影响。最理想的方法是,选择的基准恰好能把待排序序列分成两个等长的子序列。
方法1 固定基准元
如果输入序列是随机的,处理时间是可以接受的。如果数组已经有序时,此时的分割就是一个非常不好的分割。
方法2 随机基准元
这是一种相对安全的策略。由于基准元的位置是随机的,那么产生的分割也不会总是会出现劣质的分割。在整个数组数字全相等时,仍然是最坏情况,时间复杂度是O(n^2)
实际上,随机化快速排序得到理论最坏情况的可能性仅为1/(2^n)。所以随机化快速排序可以对于绝大多数输入数据达到O(nlogn)的期望时间复杂度。
方法3 三数取中
引入的原因:虽然随机选取基准时,减少出现不好分割的几率,但是还是最坏情况下还是O(n^2),要缓解这种情况,就引入了三数取中选取基准。
分析:最佳的划分是将待排序的序列分成等长的子序列,最佳的状态我们可以使用序列的中间的值,也就是第N/2个数。可是,这很难算出来,并且会明显减慢快速排序的速度。这样的中值的估计可以通过随机选取三个元素并用它们的中值作为基准元而得到。事实上,随机性并没有多大的帮助,因此一般的做法是使用左端、右端和中心位置上的三个元素的中值作为基准元。
冒泡排序算法的改进
1.设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
2.传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,我们考虑利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排序趟数几乎减少了一半。
用循环比递归效率高吗?
递归和循环两者完全可以互换。不能完全决定性地说循环地效率比递归的效率高。
递归算法
优点:代码简洁、清晰,并且容易验证正确性。
缺点:它的运行需要较多次数的函数调用,如果调用层数比较深,需要增加额外的堆栈处理(还有可能出现堆栈溢出的情况),比如参数传递需要压栈等操作,会对执行效率有一定影响。
但是,对于某些问题,如果不使用递归,那将是极端难看的代码。在编译器优化后,对于多次调用的函数处理会有非常好的效率优化,效率未必低于循环。
循环算法
优点:速度快,结构简单。
缺点:并不能解决所有的问题。有的问题适合使用递归而不是循环。如果使用循环并不困难的话,最好使用循环。
请简述 KMP 算法
在一个字符串中查找是否包含目标的匹配字符串。
其主要思想是每趟比较过程让子串先后滑动一个合适的位置。
当发生不匹配的情况时,不是右移一位,而是移动(当前匹配的长度– 当前匹配子串的部分匹配值)位。
考查散列表
哈希表是什么,怎么理解哈希表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数
解决哈希冲突的方法
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。
1) 线性探测法
2) 平方探测法
3) 伪随机序列法
4) 拉链法
在数组中查找对称键值对
追踪遍历的完整路径
查找数组是否是另一个数组的子集
检查给定的数组是否不相交
相关文章:
算法与数据结构面试题
算法与数据结构面试题 加油! 考查数据结构本身 什么是数据结构 简单地说,数据结构是以某种特定的布局方式存储数据的容器。这种“布局方式”决定了数据结构对于某些操作是高效的,而对于其他操作则是低效的。首先我们需要理解各种数据结构&a…...
尚硅谷shell脚本学习
视频:【尚硅谷】Shell脚本从入门到实战_哔哩哔哩_bilibili 学一点shell脚本能帮助进行自动化操作。苹果电脑默认环境是/bin/bash/ 通过echo $SHELL 可以查看苹果本机的内核,我的属于/bin/zsh/.注意zsh和bash没有什么区别。 一、Shell脚本入门 1&#…...
设计模式分类与定义(高软55)
系列文章目录 设计模式 文章目录 系列文章目录前言一、设计模式分类二、设计模式定义三、真题总结 前言 本节讲明常用设计模式的定义、关键点知识,很有意义哦。 一、设计模式分类 二、设计模式定义 三、真题 总结 就是高软笔记,大佬请略过!...
天梯赛 L2-025 分而治之
这个题的主要考点还是邻接表建图,很简单的一道题,每次只需要判断没有被摧毁的城市邻居是不是都被摧毁了。 #include<bits/stdc.h> using namespace std; int main(){int n,m;cin>>n>>m;vector<vector<int>> g(n1);for(in…...
MySQL的进阶语法7(索引-B+Tree 、Hash、聚集索引 、二级索引(回表查询)、索引的使用及设计原则
目录 一、索引概述 1.1 基本介绍 1.2 基本演示 1.3 特点及优势 二、索引结构 2.1 概述 2.2 二叉树 2.3 B-Tree 2.4 BTree 2.5 Hash 2.5.1 结构 2.5.2 特点 2.5.3 存储引擎支持 三、索引的分类 3.1 索引分类 3.2 聚集索引和二级索引 3.2.1 聚集索引和二级…...
芯片射频前端电路架构
2.4GHz射频前端电路的设计需要平衡多方面性能需求,是无线通信系统的关键技术环节,主要由以下几个关键模块组成: 1. 发射链路 - 数字信号转换 - 调制电路 -本地振荡器 - 功率放大器 - 天线匹配网络 2. 接收链路 - 低噪声放大器(LNA)…...
使用STM32CubeMX和Keil在STM32上创建并运行一个简单的FreeRTOS多任务程序
目标 利用FreeRTOS运行两个任务,分别为点灯和OLED屏的显示。 利用STM32CubeMX生成Keil工程和相关初始化代码 知识回顾 之前已经利用STM32CubeMX生成过Keil工程和相关初始化代码了,可以去回顾一下,详情见:https://blog.csdn.ne…...
Spring AI Alibaba 快速开发生成式 Java AI 应用
Spring AI Alibaba 是一款 Java 语言实现的 AI 应用开发框架,旨在简化 Java AI 应用程序开发,让 Java 开发者像使用 Spring 开发普通应用一样开发 AI 应用。Spring AI Alibaba 基于 Spring AI 开源项目构建,默认提供阿里云基础模型服务、开源…...
记录学习的第十七天
今天对昨天下午的洛谷蓝桥杯模拟赛和今天早上的力扣周赛进行复盘。 昨天的蓝桥杯模拟赛,硬坐了4个小时,只会做前面的三道入门题。😥而且第一道填空题竟然还算错了。其他的五道题我都没啥思路了,实在难受啊! Q1:这道题硬…...
穿透单链表的神秘屏障,洞察数据结构的真谛
❤个人主页:折枝寄北的博客 ❤专栏位置:数据结构 单链表实现逻辑 0. 前言1. 概念及结构2. 实现逻辑2.1 相关函数的声明2.2 函数代码实现2.2.1 打印2.2.2 创建新节点2.2.3 尾插2.2.4 头插2.2.5 尾删2.2.6 头删2.2.7 查找2.2.8 pos位置前插入2.2.9 pos位置…...
腾讯云智测试开发面经
1、投递时间线 2.20投递简历,3.11第一轮面试,3.30第二轮面试,4.4第三轮面试,4.10第四轮面试,4.11offer意向书 2、第一轮面试 第一轮面试技术面,面试官是导师,面试时长40多分钟 1)…...
react+antd封装一个可回车自定义option的select并且与某些内容相互禁用
需求背景 一个select框 现在要求可多选 并且原有一个any的选项 其他选项为输入后回车自己增加 若选择了any 则其他选项不可选择反之选择其他选项any不可选择 并且回车新增时也不可直接加入到选中数组只加入到option内 并且不可重复添加新内容 实现过程 <Form.Item …...
笔记1——数据通信网络基础
一、概述 数据通信网络:由路由器、交换机、防火墙、无线设备以终端构成的网络 功能:实现数据互通 二、网络设备 交换机: 特点:距离终端用户最近的设备 作用:终端接入、二层交换机 广播域:交换机连接的终端构成一个广播…...
全国产FMC子卡-16bit 8通道2.4G
国产化FMC DA子卡,16bit 8通道2.4GS/s 全国产FMC子卡是一款高分辨率、高采样率的全国产多通道标准双宽DAC FMC子板。其接口电气和结构设计均依据FMC标准(ANSI/VITA 57.1),通过两个高密度FMC连接器(HPC)连接至FPGA载板。它提供8路A…...
ZLMediaKit 源码分析——[4] ZLToolKit 中EventPoller之异步任务处理
系列文章目录 第一篇 基于SRS 的 WebRTC 环境搭建 第二篇 基于SRS 实现RTSP接入与WebRTC播放 第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建 第四篇 WebRTC学习一:获取音频和视频设备 第五篇 WebRTC学习二:WebRTC音视频数据采集 第六篇 WebRTC学习三…...
基于 DeepSeek 与天地图搭建创新地理信息应用
一、技术背景 DeepSeek 是由国内公司研发的一款具有强大参数规模与性能的大语言模型,它能够处理复杂的自然语言指令,提供丰富的分析与建议。天地图则是国家地理信息公共服务平台,提供权威、丰富的地理信息数据,涵盖卫星影像、矢量…...
python函数装饰器
python函数装饰器 声明:博主并没有系统学习过python语言,在实际项目中遇到关于python不懂的语法,这里仅作为个人学习积累笔记 1.1 python函数相关基础 深入了解python函数装饰器移步:Python 函数装饰器 下面的笔记来源于上述链接…...
AI战略群与星际之门:软银AI投资版图计划深度解析
一、星际之门:万亿美元级 AI 基础设施革命 1.1 项目背景与战略定位 在 AI 技术迅猛发展的今天,算力已成为推动其前进的核心动力。软银联合 OpenAI、甲骨文、英伟达、微软、arm推出的 “星际之门”(Stargate)计划,无疑是 AI 领域的一颗重磅炸弹。作为 AI 领域史上最大单笔…...
Modbus TCP转profibusDP网关接防撞雷达快速配置
Modbus TCP转profibusDP网关接防撞雷达快速配置 在工业自动化领域中,不同的设备可能使用不同的通信协议。当需要将使用 ModbusTCP 协议的防撞雷达连接到ProfibusDP网络时,需要使用协议转换器来实现协议的转换。 本文将详细介绍如何通过ModbusTCP转Profi…...
O(1) 时间复杂度数据设计题
0x00 preface 所谓 O ( 1 ) O(1) O(1) A P I API API 设计,并不是说,时间复杂度必须是**“总是”常数级别的。 对于一个操作来说,如果他偶尔是 O ( N ) O(N) O(N) 的,大部分时间都是 O ( 1 ) O(1) O(1) 的,并且&a…...
基于Spring AI与Ollama构建本地DeepSeek对话机器人
1、安装ollama: 打开Ollama下载官网,根据自己的操作系统下载相应版本的安装文件。 由于Ollama默认安装在C盘,而Ollama和模型文件都非常大,如果安装在C盘非常占用系统空间,可以使用下面的方法将Ollama安装到指定为止 …...
边缘计算赋能淘宝API:分布式节点缓存降低高并发延迟
以下是关于 “边缘计算赋能淘宝 API:分布式节点缓存降低高并发延迟” 的相关内容介绍: 背景 淘宝作为大型电商平台,每天面临海量的用户访问和高并发请求。在传统的集中式计算架构下,处理如此大规模的请求容易导致网络延迟、响应速…...
Keepalived+LVS+nginx高可用架构
注明:所有软件已经下载好,防火墙和SELinux已经全部关闭 一.搭建NFS 1.服务端 1.创建文件 [rootnfs ~]# mkdir -p /nfs/data 2、修改权限 [rootnfs ~]# chmod orw /nfs/data 3、写配置文件 [rootnfs ~]# cat /etc/exports /nfs/data 192.168.111.118(r…...
CMake学习--如何在CMake中编译静态库、动态库并在主程序中调用
目录 一、背景知识二、使用方法(一)编译静态库(二)编译动态库(三)在主程序中调用库 三、总结 一、背景知识 在C/C开发中,库(Library)是预先编译好的代码集合,…...
技术回顾day3
1.获取文件信息、获取视频信息 走的都是同一个方法:baseController里面的getFile。 在getFile方法里面进行判断文件的类型,判断是不是m3u8类型或者ts类型做一些额外的处理。 获取信息底层就是读取文件,然后写入response的OutputStream ou…...
【dp + 裴蜀定理】P8646 [蓝桥杯 2017 省 AB] 包子凑数 题解
P8646 [蓝桥杯 2017 省 AB] 包子凑数 题解 题目传送门 P8646 [蓝桥杯 2017 省 AB] 包子凑数 一、题目描述 小明发现包子铺有N种蒸笼,每种能放A_i个包子(无限供应)。问有多少个正整数X无法被这些蒸笼数量的组合表示出来。若无限多个则输出…...
在HarmonyOS NEXT 开发中,如何指定一个号码,拉起系统拨号页面
大家好,我是 V 哥。 《鸿蒙 HarmonyOS 开发之路 卷1 ArkTS篇》已经出版上市了哈,有需要的朋友可以关注一下,卷2应用开发篇也马上要出版了,V 哥正在紧锣密鼓的写鸿蒙开发实战卷3的教材,卷3主要以项目实战为主࿰…...
网络华为HCIA+HCIP 策略路由,双点双向
目录 路由策略,策略路由 策略路由优势 策略路由分类 接口策略路由 双点双向 双点双向路由引入特点: 联系 路由回灌和环路问题 路由策略,策略路由 路由策略:是对路由条目进行控制,通过控制路由条目影响报文的转发路径,即路…...
探索Doris:日志分析的新宠,是否能取代老牌ES?
在大数据时代,日志存储与分析对于企业的运营和决策起着至关重要的作用。Elasticsearch(简称 ES)作为一款广泛应用的开源分布式搜索和分析引擎,长期以来在日志管理领域占据着举足轻重的地位。然而,随着技术的不断发展&a…...
常见电源模块设计
目录 1. 5V电源模块 2. 3.3V电源模块 3. 1.9V电源模块 4. 220V转12V电源模块 1. 5V电源模块 参考电路 电路说明: 这个电路采用的是稳压芯片78L05,我是用的12V的电源模块转成为5V,为后续的供电。 2. 3.3V电源模块 参考电路: 电路说明…...
虚幻引擎控制角色跟随移动方向旋转的方法
在UE5中,要控制角色随移动方向旋转,可以使用蓝图和C两种方式来实现。 使用蓝图 1、选中角色移动组件,勾选将旋转朝向运动。 2、选中当前角色类 取消勾选使用控制器旋转的几个选项 3、这时,摄像机会跟着角色一起旋转。如果不希望…...
Oracle 23ai Vector Search 系列之3 集成嵌入生成模型(Embedding Model)到数据库示例,以及常见错误
文章目录 Oracle 23ai Vector Search 系列之3 集成嵌入生成模型(Embedding Model)到数据库示例,以及常见错误使用安装了Oracle 23ai 的虚拟机(Oracle Database 23ai Free VirtualBox Appliance)1.下载[Oracle VM Virtu…...
RISC-V debug专栏2 --- Debug Module(DM)
Debug Module(DM)的核心功能 DM 就像一个翻译官,负责把调试器的抽象指令(比如 “暂停处理器”)转换成硬件能听懂的具体操作。它必须实现以下基本功能: 必要功能(必须实现)ÿ…...
LLM 分词器Tokenizer 如何从 0 到 1 训练出来
写在前面 大型语言模型(LLM)处理的是人类的自然语言,但计算机本质上只能理解数字。Tokenizer(分词器) 就是架在自然语言和计算机数字表示之间的一座至关重要的桥梁。它负责将我们输入的文本字符串分解成模型能够理解的最小单元——Token,并将这些 Token 转换成对应的数字…...
蓝桥杯冲刺:一维前缀和
系列文章目录 蓝桥杯系列:一维前缀和 文章目录 系列文章目录前言一、暴力的写法:二、一维前缀和的模板: 具体实现: 三、具体例题:求和 1.题目参考:2.以下是具体代码实现: 总结 前言 上次我介绍…...
光学关键尺寸量测设备市场报告:2024年全球市场销售额达到了14.75亿美元
一、引言 光学关键尺寸量测设备作为半导体制造、精密加工等领域的核心工具,其重要性不言而喻。随着科技的飞速发展,这些设备在提升产品精度、缩短研发周期、降低生产成本等方面发挥着越来越关键的作用。本报告旨在深入分析光学关键尺寸量测设备的技术特…...
链表的操作-反转链表
链表 160相交链表 代码 class Solution { public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* h1headA;ListNode* h2headB;while(h1&&h2){if(h1!h2){h1h1->next;h2h2->next;}else{return h1;}}if(h1nullptr){h1headB;}else{h…...
2025 年浙江危化品经营单位考试攻略分享
浙江的考试由省应急管理部门主导。理论考试突出危化品在电商、物流等新兴业态下的安全管理知识,这与浙江发达的电商产业紧密相关。对危险化学品的环境危害及防治知识考查细致。实际操作考核模拟杭州、宁波等地危化品仓储物流中心的作业情况。 报名材料准备齐全后…...
python使用cookie、session、selenium实现网站登录(爬取信息)
一、使用cookie 这段代码演示了如何使用Python的urllib和http.cookiejar模块来实现网站的模拟登录,并在登录后访问需要认证的页面。 # 导入必要的库 import requests from urllib import request, parse# 1. 导入http.cookiejar模块中的CookieJar类,用…...
STM32开发板上生成PWM正弦波
在STM32开发板上生成正弦波通常需要结合定时器(TIM)、数模转换器(DAC)或脉宽调制(PWM)以及时钟系统的配置。以下是分步指南: 方法1:使用DAC 定时器(推荐) 步…...
Spring Boot 实现文件秒传功能
前言 在开发Web应用时,文件上传是一个常见需求。然而,当用户需要上传大文件或相同文件多次时,会造成带宽浪费和服务器存储冗余。此时可以使用文件秒传技术通过识别重复文件,实现瞬间完成上传的效果,大大提升了用户体验…...
【Vue2】数据绑定_MVVM模型_数据代理_事件处理
目录 一、 数据绑定 1. Vue中有2种数据绑定的方式: 2. 响应式原理 el 与 data 的两种写法 二、 MVVM模型 三、 数据代理 1.回顾Object defineproperty方法 2. 何为数据代理 3.Vue中的数据代理 四、 事件处理 1.事件的基本使用: 2. Vue中的事…...
Python数据类型-dict
Python数据类型-dict 字典是Python中一种非常强大且常用的数据类型,它使用键-值对(key-value)的形式存储数据。 1. 字典的基本特性 无序集合:字典中的元素没有顺序概念可变(mutable):可以动态添加、修改和删除元素键必须唯一且不可变&…...
win10之mysql server 8.0.41安装
一 mysql server 下载 官网下载地址页面 https://dev.mysql.com/downloads/mysql/二 免装版使用步骤 1 解压 下载完成后,解压文件夹,如下所示: 2 执行安装命令 D:\soft\mysql\mysql-8.0.41-winx64\mysql-8.0.41-winx64\bin>mysqld --install Service successfully in…...
解决Oracle PL/SQL中“表或视图不存在“错误的完整指南
解决Oracle PL/SQL中"表或视图不存在"错误的完整指南 前言问题概述根本原因分析一、 编译时与运行时验证差异二、权限问题三、 Schema命名问题 实际案例演示案例1:动态分表查询案例2:权限不足的场景 实用排查步骤排查流程图最佳实践建议解决方…...
从实用的角度聊聊Linux下文本编辑器VIM
本文从实用的角度聊聊Vim的常用命令。何为实用?我举个不实用的例子大家就明白了,用vim写代码。;) “vim是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用,和Emacs并列成…...
MySQL的进阶语法8(SQL优化——insert、主键、order by、group by、limit、count和update)
目录 一、插入数据 1.1 insert 1.2 大批量插入数据 二、主键优化 2.1 数据组织方式 2.2 页分裂 2.2.1 主键顺序插入效果 2.2.2 主键乱序插入效果 2.3 页合并 2.4 索引设计原则 三、order by优化 3.1 执行以下两条语句(无索引) 3.2 创建索引…...
STM32F103C8T6单片机硬核原理篇:讨论GPIO的基本原理篇章1——只讨论我们的GPIO简单输入和输出
目录 前言 输出时的GPIO控制部分 标准库是如何操作寄存器完成GPIO驱动的初始化的? 问题1:如何掌握GPIO的编程细节——跟寄存器如何打交道 问题2:哪些寄存器,去哪里找呢? 问题三,寄存器的含义ÿ…...
FreeRTOS源码下载分享
FreeRTOS源码下载分享 官网下载太慢了,分享下FreeRTOSv202411 FreeRTOSv202411.00.zip 链接: https://pan.baidu.com/s/1P4sVS5WroYEl0WTlPD7GXg 提取码: g6aq...
PyArrow 核心技术与应用:高效数据处理与跨生态集成实践
Apache Arrow 作为列式内存数据格式的行业标准,其 Python 接口 PyArrow 正在重塑数据科学生态。本文深入解析 PyArrow 的核心计算能力,涵盖统计函数、分组聚合、窗口操作及跨库集成,通过完整代码示例演示如何利用其高性能特性优化数据处理流程…...