深耕专业教研,探索前沿技术
信息技术来源:浙江强基联盟2026年5月高三联考

第 15 题

答案与解析

第(2)①小题

参考答案

6

程序分析

for i in range(1, n):
    key = data[i]
    ...

外层循环从 i=1 开始,data[0] 先单独构成已有序部分。每一轮取出 data[i] 并保存为 key,再通过下面的内层过程把它插入前面的已有序部分;一轮结束后,已有序范围增加一个元素。

j = i - 1
while j >= 0:
    if data[j][0]>key[0] or (data[j][0]==key[0] and data[j][1]<key[1]):
        data[j + 1] = data[j]
        j -= 1
    else:
        break
data[j + 1] = key

j=i-1 使 j 从已有序部分的末端开始向左比较。当已有元素的到达时间晚于 key,或到达时间相同但规格字母小于 key 时,该元素应排在 key 后面,于是加框语句把它右移一位,j 再向左继续查找;条件不成立时停止。循环结束后,右移过程在 j+1 处留下插入位置,程序把 key 写入该处。因此数据按到达时间升序排列,同一时间内按规格字母降序排列;加框语句的执行次数就是已有元素右移的总次数。

s=""
for i in range(n):
    s=s+data[i][1]
return s

排序完成后,程序按当前顺序取出每个元素中的规格字母 data[i][1],依次拼接到字符串 s 的末尾,最后返回拼接结果。

解题思路

外层循环逐个取出 data[i] 作为 key,内层循环从已有序部分的末端向左寻找插入位置,并把不符合顺序的元素依次右移,最后执行 data[j+1]=key。这是插入排序的典型结构。

按外层循环逐轮插入。加框语句每执行一次,就有一个已有元素向右移动:

i key 本轮向右移动的已有元素 次数
1 07:45,D 07:45,A 1
2 07:45,A 无 0
3 07:47,C 无 0
4 07:47,B 无 0
5 07:45,B 从右向左依次为 07:47,B、07:47,C、07:45,A、07:45,A 4
6 07:47,C 07:47,B 1

7个元素的所有外层轮次都已列出,加框语句总执行次数为 1+4+1=6。

第(3)小题

参考答案
  1. pos = len(top)

  2. if top[mid] >= cur

  3. top[pos] = cur

程序分析

n = len(box)
top=[] #每个堆最下面的一个位置
top_idx=[]
prev=[-1]*n

n为集装箱数量。top与top_idx初始为空,prev为每个集装箱预留一个值为-1的记录位置。各列表的含义需结合后续存入和读取的数据确定;题面top后的注释与后文操作有冲突,以下按实际程序分析。

for i in range(n):
    cur = ord(box[i])-65
    left,right = 0,len(top)
    ①
    ...

循环按到港顺序逐个处理集装箱。ord(box[i])-65 把规格 A~F 转换为 0~5,规格越大,得到的 cur 越大。

left 和 right 分别从 0 与 len(top) 开始,后续将在这个范围内确定新集装箱应放入哪一堆。

while left < right:
    mid = (left + right) // 2
    ②:
        pos = mid
        right = mid
    else:
        left=mid+1

循环每次取中间位置 mid,再根据空②的判断缩小左右边界,属于对分查找。条件成立时先把 mid 记入 pos,再令 right = mid 继续向左查找;条件不成立时令 left = mid+1。因此,这段代码要找的是满足条件的最左位置。

if pos < len(top):
    prev[i] = top_idx[pos]
    ③
    top_idx[pos] = i
else:
    top.append(cur)
    top_idx.append(i)

新建堆时,top追加规格编码cur,top_idx追加当前箱子的下标i,可据此确定两者分别记录各堆堆顶规格和堆顶下标。放入已有堆时,先把原堆顶下标存入prev[i],再把top_idx[pos]更新为i,因此prev[i]记录当前箱子下面相邻箱子的下标,-1表示下方没有箱子。

for i in range(len(top)):
    pile = []
    curr_idx = top_idx[i] # 从堆顶开始
    while curr_idx != -1:
        pile.append(box[curr_idx])
        curr_idx = prev[curr_idx]
return len(top)

程序从每一堆的 top_idx[i] 开始,根据 prev 中保存的下方集装箱下标逐层向下访问,直至遇到 -1,由此还原各堆的集装箱。最终 len(top) 就是建立的堆数。

填空分析

①

查找未命中时,需要进入新建堆的else分支。将pos初始值设为len(top),即可使pos < len(top)不成立;找到合适的堆后,循环中的pos = mid会记录其位置。初始top为空时也能直接新建第一堆。故填:

pos = len(top)

②

题目要求在堆顶规格不小于cur的堆中,选择堆顶规格最小的一堆。top需要按非降序保存堆顶规格,这样最左侧满足top[mid] >= cur的位置就是目标。条件成立时记录mid,并令right = mid向左查找;条件不成立时,该位置及其左侧规格均过小,应令left = mid+1。

空②包含if关键字,题面已经给出冒号,因此填:

if top[mid] >= cur

③

当前箱子放入第pos堆后成为新的堆顶,规格应更新为cur,故填:

top[pos] = cur

这一更新也维持了top的非降序:pos左侧各值都小于cur,右侧各值不小于原top[pos],也就不小于cur。若查找未命中,则已有各堆顶都小于cur,将cur追加到末尾仍然有序。因此从空列表开始,每轮都能继续进行对分查找。

第(1)小题

参考答案

3

按到港顺序处理,每次选择堆顶规格不小于新箱、且堆顶规格最小的一堆;找不到时才新建堆。只需跟踪各堆当前堆顶,变化如下:

到港次序 新箱规格 各堆堆顶规格(按建堆顺序)
1 C C
2 C C
3 D C、D
4 B B、D
5 A A、D
6 C A、C
7 A A、C
8 C A、C
9 D A、C、D
10 B A、B、D
11 A A、B、D

例如,第6个箱子 C 到港时,不能放在堆顶为 A 的第1堆上,可放在堆顶为 D 的第2堆上;第9个箱子 D 到港时,已有堆顶分别为 A、C,均小于 D,因此必须新建第3堆。最终可得到三堆,按从底到顶的顺序分别为 [C,C,B,A,A,A]、[D,C,C,B]、[D]。

此外,第5、第6、第9个箱子的规格依次为 A、C、D,体积按到港顺序严格增大。任意两个都不能放在同一堆:后到的较大箱子既不能放在先到的小箱子上,也不能放到它的下方。因此至少需要3堆,而上述方案恰好使用3堆,最少堆数为3。

第(2)②小题

参考答案

DBAACCB

共用程序分析见第(2)①小题。

按照前面的排序规则,先处理07:45到达的记录,再处理07:47到达的记录;同一到达时间内,按规格字母从大到小排列。

到达时间 原有规格 排序后的规格顺序
07:45 A、D、A、B D、B、A、A
07:47 C、B、C C、C、B

最后一个 for 循环依次把排序后的规格字母拼接到 s 中,因此返回字符串 'DBAACCB'。