题目(共8小题)
1.(单选)下列适用邻接表存储的是
A. 有向图 B. 无向图 C. 稠密图 D. 稀疏图
2.(单选)假设4个作业到达系统的时刻和运行时间见表,系统在t=2时开始作业调度。若分别采用先来先服务和短作业优先调度算法,则选中的作业分别是
|----|-------|------|
| 作业 | 到达时刻t | 运行时间 |
| J1 | 0 | 3 |
| J2 | 1 | 3 |
| J3 | 1 | 2 |
| J4 | 3 | 1 |
A. J1,J3 B. J2,J3 C. J2,J4 D. J1,J4
3.(单选)下列选项中的黑色图形,是凸集的为
从上到下依次为选项A,B,C,D
4.(单选)以下哪项描述关于动态规划求解斐波那契数列问题时的空间优化是正确的
A. 在求解过程中,只有前两个斐波那契数的值是需要保留的
B. 动态规划可以通过记忆化递归避免空间优化
C. 需要保存所有计算过的斐波那契数
D. 通过修改递归公式来减少空间复杂度
5.(单选)以下叙述正确的是
A. 若带链队列的队头指针与队尾指针相同,则队列中至少有一个元素
B. 带链栈的栈底指针是随栈的操作而动态变化的
C. 带链栈空的条件是top==NULL
D. 带链队列空的条件是front=rear=-1
6.(单选)以下哪个问题无法通过贪心算法获得最优解
A. 0-1背包问题
B. 单源最短路径(非负权)
C.最小生成树
D.活动选择问题
7.(单选)在图的广度优先搜索(BFS)中,下列哪种情况会导致算法无法访问所有节点?
A. 图是连通的
B. 起始节点被移除
C. 图中存在环
D. 边数过少
8.(单选)要设计一个类似微信抢红包的程序,要求存储每个人所抢到的金额数,且能方便地通过某个人的账号ID快速找到这个人所抢到的金额数。完成此工作,最好采用以下的哪种数据结构实现?
A. 哈希表 B. 线性链表 C.二叉链表 D.数组
解答
1.【答案】D
【解析】邻接表 是一种图的存储结构,它通过链表或数组列表的方式存储每个顶点的邻居顶点。这种结构特别适合存储稀疏图(即边数相对较少的图),因为邻接表只存储实际存在的边,从而节省内存空间。
相比之下:
-
稠密图(边数较多)通常更适合用邻接矩阵存储,因为邻接矩阵可以快速访问任意两个顶点之间是否有边,但空间开销较大。
-
有向图 和无向图都可以用邻接表存储,但这不是邻接表的独特优势------邻接表同样适用于这两种图类型,但问题焦点在于"适用"性,即哪种图最能体现邻接表的效率优势。
因此,基于数据结构的基本原理,邻接表最适用于稀疏图。
2.【答案】A
**【解析】**根据给定的作业信息(到达时刻和运行时间)以及系统在 t=2 时开始调度,分别采用先来先服务(FCFS)和短作业优先(SJF)调度算法进行分析:
-
先来先服务(FCFS)算法:按照作业到达的顺序进行调度。在 t=2 时,已到达的作业有 J1(到达时刻 t=0)、J2(到达时刻 t=1)和 J3(到达时刻 t=1)。J4 在 t=3 到达,因此未在调度考虑范围内。FCFS 选择最早到达的作业,即 J1。
-
短作业优先(SJF)算法:选择运行时间最短的作业。在 t=2 时,可用的作业有 J1(运行时间 3)、J2(运行时间 3)和 J3(运行时间 2)。其中 J3 的运行时间最短,因此 SJF 选择 J3。
因此,先来先服务算法选中的作业是 J1,短作业优先算法选中的作业是 J3。对应选项中的"J1, J3"。
3.【答案】A
**【解析】**根据凸集的定义:集合中任意两点之间的线段上的所有点都属于该集合。分析选项中的图形:
-
A. 纯黑色椭圆:椭圆是凸集,因为任意两点在椭圆内,连接它们的线段也完全在椭圆内。
-
B. 中间白色、外围黑色的椭圆环:这不是凸集,因为取外环上相对的两点,连接它们的线段会穿过白色区域,不全部在阴影内。
-
C. 类似十字的黑色图形:这不是凸集,因为取十字不同臂上的两点,线段可能穿过非阴影区域。
-
D. 弯曲的黑色图形:这不是凸集,因为形状有凹陷,取两点线段可能部分不在阴影内。
因此,阴影部分构成凸集的图形是A。
4.【答案】A
**【解析】**斐波那契数列的标准定义为:F(0) = 0, F(1) = 1,F(n) = F(n-1) + F(n-2)(当 n > 1)。在动态规划中,求解斐波那契数列通常有两种方法:
-
未优化的方法(如自底向上带数组):使用一个数组存储所有计算过的斐波那契数,时间复杂度和空间复杂度均为 O(n)。
-
空间优化方法(迭代优化版) :由于计算 F(n) 只需要前两个值(F(n-1) 和 F(n-2)),我们可以只用两个变量(例如
prev
和curr
)来存储这些值,通过迭代方式更新。这样,空间复杂度优化为 O(1),而时间复杂度仍为 O(n)。
现在,分析每个选项:
-
A. 在求解过程中,只有前两个斐波那契数的值是需要保留的
正确。在优化后的动态规划实现中(如迭代方法),我们只需保留前两个值(例如 F(n-1) 和 F(n-2))来计算下一个值 F(n)。这减少了空间使用,从 O(n) 优化到 O(1)。例如,计算 F(5) 只需要 F(4) 和 F(3),以此类推。
-
B. 动态规划可以通过记忆化递归避免空间优化
错误。记忆化递归(memoization)是动态规划的一种形式(自顶向下),它使用哈希表或数组存储已计算的值以避免重复计算,但会占用 O(n) 空间(用于存储表,加上递归栈空间)。这并没有"避免空间优化";相反,记忆化递归本身是一种空间换时间的优化,但空间复杂度仍为 O(n)。实际上,记忆化递归需要额外空间,而空间优化(如使用迭代方法)可以进一步减少空间使用。因此,这个选项的描述不准确。
-
C. 需要保存所有计算过的斐波那契数
错误。在未优化的动态规划中(如基于数组的自底向上方法),确实需要保存所有计算过的值,但这不是必须的。优化后(如使用两个变量的迭代方法),我们不需要保存所有值,只保留前两个即可。因此,空间优化后,这个描述是错误的。
-
D. 通过修改递归公式来减少空间复杂度
错误。空间优化不是通过修改递归公式实现的,因为递归公式 F(n) = F(n-1) + F(n-2) 本身没有改变。优化是通过改变实现方式来实现的,例如:从递归或数组存储转换为仅用两个变量的迭代方法。递归公式是固定的,空间优化是编码技巧的改进,而不是公式的修改。
为什么空间优化有效?
在斐波那契数列的动态规划中,空间优化的核心在于利用数列的递推性质:每个数只依赖前两个数。因此,优化方法只维护两个变量。示例代码(Python):
python
def fib(n):
if n <= 1:
return n
prev, curr = 0, 1 # 初始值 F(0) 和 F(1)
for i in range(2, n + 1):
prev, curr = curr, prev + curr # 只保留前两个值
return curr
5.【答案】C
【解析】
-
选项A: "若带链队列的队头指针与队尾指针相同,则队列中至少有一个元素"
对于链式队列(带链队列),当头指针(front)和尾指针(rear)相同时,队列可能处于两种状态:要么为空(两者都为NULL),要么只有一个元素(两者都指向同一个节点)。因此,头尾指针相同并不保证至少有一个元素(可能为空),所以该选项错误。
-
选项B: "带链栈的栈底指针是随栈的操作而动态变化的"
在链式栈(带链栈)中,栈底指针通常是指向链表第一个节点的指针。栈的操作(如push或pop)主要影响栈顶指针(top),而栈底指针在栈生命周期内通常是固定的(除非整个栈被销毁或重建),不会随每个操作动态变化。因此,该选项错误。
-
选项C: "带链栈空的条件是top==NULL"
对于链式栈,栈顶指针(top)指向栈顶元素。当栈为空时,top指针应为NULL。这是链式栈空的标准条件,因此该选项正确。
-
选项D: "带链队列空的条件是front=rear=-1"
链式队列(带链队列)通常使用指针实现,而不是数组索引。空队列的条件通常是front指针为NULL或front == rear(但具体实现可能不同)。使用"-1"更常见于基于数组的队列初始化,而不是链式队列。对于链式队列,空条件应为front == NULL或类似,而不是front=rear=-1。因此,该选项错误。
6.【答案】A
【解析】
-
A. 0-1背包问题 :0-1背包问题中,给定一组物品,每个有重量和价值,你需要选择一些物品放入背包,使总价值最大,但总重量不超过背包容量。物品不能被分割(0-1表示要么取整,要么不取)。贪心算法不能保证最优解,因为它可能选择高价值但重量大的物品,导致浪费空间;或低价值密度但总体更好的组合。实际上,0-1背包问题通常用动态规划求解,不是贪心算法。贪心算法只有在物品可分割(如分数背包)时才能保证最优解。所以,0-1背包问题无法通过贪心算法获得最优解。
-
B. 单源最短路径(非负权) :这指的是Dijkstra算法,它是一种贪心算法,用于在非负权重的图中找到从源点到所有其他点的最短路径。Dijkstra算法是贪心的,并在非负权重下保证最优解。所以,单源最短路径(非负权)可以通过贪心算法获得最优解。
-
C. 最小生成树 :最小生成树问题(如Kruskal或Prim算法)都是贪心算法。Kruskal按边权重排序并添加不形成环的边;Prim从点开始添加最小边。两者都保证找到最小生成树。所以,最小生成树可以通过贪心算法获得最优解。
-
D. 活动选择问题 :活动选择问题涉及选择一组不重叠的活动以最大化活动数量或满足某些目标。贪心算法如按结束时间排序并选择最早结束的活动,保证找到最优解(最大兼容活动集)。所以,活动选择问题可以通过贪心算法获得最优解。
7.【答案】B
【解析】
-
A. 图是连通的 :如果图连通,BFS从任何节点开始都能访问所有节点。因此,这种情况不会导致无法访问所有节点。
-
B. 起始节点被移除:这是正确选项。如果从图中移除了起始节点(或起始节点不存在),BFS将无法开始遍历(没有起点),因此无法访问任何节点。另外,即使起始节点存在但与其他节点不连通(如孤立节点),BFS也只能访问该节点自身,无法访问其他节点(如果图有多个连通分量)。题目中的"起始节点被移除"直接导致BFS无法访问任何节点或无法访问其他连通分量的节点。
-
C. 图中存在环:环的存在不影响BFS的遍历能力。BFS能够正确处理环(通过标记已访问节点避免重复访问),因此仍能访问所有可达节点。
-
D. 边数过少:边数少可能使图成为稀疏图,但不一定导致无法访问所有节点。只要图是连通的(或起始节点在包含所有节点的连通分量中),BFS就能访问所有节点。边数少也可能意味着图是非连通的(如多个孤立节点),但"边数过少"本身不是直接原因。
8.【答案】A
【解析】根据问题要求,需要存储每个人所抢到的金额数,并能通过账号ID快速查找对应的金额。关键点是"快速找到",因此需要一种支持高效查找操作的数据结构。
-
A. 哈希表:哈希表通过哈希函数将键(账号ID)映射到存储位置,使得查找、插入和删除操作的平均时间复杂度为O(1)。这非常适合通过ID快速查找金额,符合要求。
-
B. 线性链表:链表需要遍历查找,平均时间复杂度为O(n),效率低下,不符合快速查找的要求。
-
C. 二叉链表:通常指二叉树的链表实现,如二叉搜索树(BST)。查找时间复杂度为O(log n)(如果平衡),但最坏情况下为O(n),且实现较哈希表复杂,效率不如哈希表。
-
D. 数组:数组需要通过索引访问,但账号ID通常不是连续整数,因此查找时需要遍历,时间复杂度为O(n),效率低。
因此,最好采用哈希表实现,选项A正确。