#GESP202609C5. 选择/判断题
选择/判断题
一、单选题(每题 2 分,共 30 分)
- 小杨用单链表保存任务序列,并同时维护头指针 head 和尾指针 tail 。在链表非空且已知 tail 的情况下,在表尾插入新结点的时间复杂度是( )。
struct Node {
int value;
Node *next;
};
Node *head;
Node *tail;
{{ select(1) }}
- 在不带哨兵结点的双向链表中,结点 p 既不是头结点也不是尾结点。删除 p 的正确代码是( )。
struct Node {
int value;
Node *prev;
Node *next;
};
{{ select(2) }}
-
p->prev = p->next; p->next = p->prev; delete p; -
p->prev->next = p; p->next->prev = p; delete p; -
p->prev->next = p->next; p->next->prev = p->prev; delete p; -
p->next = p->prev; p->prev->next = nullptr; delete p;
- 下面函数使用快慢指针查找单链表的中间结点。横线处应填写( )。
struct Node {
int value;
Node *next;
};
Node *middle(Node *head) {
Node *slow = head;
Node *fast = head;
while (fast != nullptr && fast->next != nullptr) {
slow = slow->next;
______________________
}
return slow;
}
{{ select(3) }}
fast = fast->next;fast = fast->next->next;fast = slow->next;fast = head->next;
- 函数 gcd(int a, int b) 定义如下,则 gcd(105, 45) 的结果是( )。
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
{{ select(4) }}
- 3
- 5
- 15
- 45
- 下面函数用于判断正整数 n 是否为质数。横线处的最佳写法是( )。
bool isPrime(int n) {
if (n < 2)
return false;
for (int i = 2; __________________; i++) {
if (n % i == 0)
return false;
}
return true;
}
{{ select(5) }}
i < ni <= n / 2i * i < n(long long) i * i <= n
- 下面代码实现线性筛法。为了保证每个合数只被其最小质因子筛去一次,横线处应填写( )。
vector<int> linearSieve(int n) {
vector<bool> composite(n + 1, false);
vector<int> primes;
for (int i = 2; i <= n; i++) {
if (!composite[i])
primes.push_back(i);
for (int p : primes) {
if ((long long)i * p > n)
break;
composite[i * p] = true;
if (__________________)
break;
}
}
return primes;
}
{{ select(6) }}
p % i == 0i % p == 0i == pi * p == n
- 根据唯一分解定理,整数 756 的正确质因数分解是( )。
{{ select(7) }}
- 函数 f(int n) 定义如下,则 f(4) 的结果是( )。
int f(int n) {
if (n == 1)
return 1;
return n + f(n - 1);
}
{{ select(8) }}
- 4
- 7
- 9
- 10
- 在升序数组中查找第一个严格大于 x 的元素位置,下面代码中的横线应填写( )。
int upperBound(const vector<int> &a, int x) {
int l = 0, r = (int)a.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (__________________) {
l = mid + 1;
} else {
r = mid;
}
}
return l;
}
{{ select(9) }}
a[mid] < xa[mid] >= xa[mid] <= xa[mid] > x
- 小杨需要把若干箱货物按原顺序分配到 days 天中,每天运输连续的若干箱,求能够完成任务的最小载重量。函数 check(cap) 判断载重量为 cap 时能否在规定天数内运完。横线处应填写( )。
long long l = maxWeight;
long long r = totalWeight;
while (l < r) {
long long mid = l + (r - l) / 2;
if (check(mid)) {
____________________
} else {
____________________
}
}
cout << l;
{{ select(10) }}
- l = mid + 1; 和 r = mid;
- r = mid; 和 l = mid + 1;
- r = mid - 1; 和 l = mid;
- l = mid; 和 r = mid - 1;
- 下面是归并排序中合并两个有序区间(升序排序)的部分代码。若希望排序保持稳定,横线处应填写( )。
while (i <= mid && j <= right) {
if (__________________) {
temp.push_back(a[i++]);
} else {
temp.push_back(a[j++]);
}
}
{{ select(11) }}
a[i] < a[j]a[i] > a[j]a[i] >= a[j]a[i] <= a[j]
- 下面快速排序的划分函数以 a[right] 为枢轴,并把不大于枢轴的元素移动到左侧。横线处应填写( )。
int partition(int a[], int left, int right) {
int pivot = a[right];
int i = left - 1;
for (int j = left; j < right; j++) {
if (__________________) {
i++;
swap(a[i], a[j]);
}
}
swap(a[i + 1], a[right]);
return i + 1;
}
{{ select(12) }}
a[j] <= pivota[j] > pivota[i] <= pivota[right] < a[j]
- 小杨要在一个教室安排尽可能多场活动,每场活动具有开始时间 start 和结束时间 end 。采用贪心算法时,正确的选择策略是( )。
struct Activity {
int start;
int end;
};
{{ select(13) }}
- 每次选择开始时间最早的活动
- 每次选择持续时间最短的活动
- 每次选择参与人数最少的活动
- 按结束时间从早到晚排序,依次选择与已选活动不冲突的活动
- 下面函数使用迭代方法求最大连续子段和。对于数组 {-2, 3, -1, 5, -6, 2} ,函数返回值是( )。
int maxSubArray(const vector<int> &a) {
int best = a[0];
int current = a[0];
for (int i = 1; i < (int)a.size(); i++) {
current = max(a[i], current + a[i]);
best = max(best, current);
}
return best;
}
{{ select(14) }}
- 5
- 6
- 7
- 8
- 数组 a 和 b 按低位在前的顺序保存两个非负大整数。下面代码实现高精度加法,横线处应填写( )。
vector<int> add(const vector<int> &a, const vector<int> &b) {
vector<int> c;
int carry = 0;
int n = max(a.size(), b.size());
for (int i = 0; i < n; i++) {
int sum = carry;
if (i < a.size())
sum += a[i];
if (i < b.size())
sum += b[i];
c.push_back(sum % 10);
____________________
}
if (carry)
c.push_back(carry);
return c;
}
{{ select(15) }}
carry = sum % 10;carry = sum;carry = sum / 10;carry = c[i] / 10;
二、判断题(每题 2 分,共 20 分)
- 下面代码在已知结点 p 的情况下,能够以 的时间在单链表的 p 结点之后插入新结点 s 。
s->next = p->next;
p->next = s;
{{ select(16) }}
- 正确
- 错误
- 下面代码可以安全地删除单链表的头结点,并使 head 指向删除后的新头结点。
Node *p = head;
delete p;
head = p->next;
{{ select(17) }}
- 正确
- 错误
- 下面欧几里得算法既适用于 a > b ,也适用于 a < b ,只要 a 、 b 是正整数。
int gcd(int a, int b) {
while (b != 0) {
int r = a % b;
a = b;
b = r;
}
return a;
}
{{ select(18) }}
- 正确
- 错误
- 下面埃氏筛从 i * i 开始标记,是因为 i * i 之前的 i 的合数倍数已经被更小的质因子标记过。
for (int i = 2; (long long)i * i <= n; i++) {
if (isPrime[i]) {
for (int j = i * i; j <= n; j += i) {
isPrime[j] = false;
}
}
}
{{ select(19) }}
- 正确
- 错误
- 下面程序的时间复杂度为 。
for (int i = 1; i <= n; i *= 2) {
cout << i << endl;
}
{{ select(20) }}
- 正确
- 错误
- 若数组 a 已按升序排列,下面函数能够返回最后一个小于等于 x 的元素下标;如果不存在,则返回-1 。
int findLastLE(const vector<int> &a, int x) {
int l = 0, r = (int)a.size() - 1;
int ans = -1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (a[mid] <= x) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ans;
}
{{ select(21) }}
- 正确
- 错误
- 快速排序中如果选取区间第一个元素作为枢轴。当输入数组已经升序排列时,其最坏时间复杂度仍为 。
{{ select(22) }}
- 正确
- 错误
- 归并排序的递推式为 ,对应的时间复杂度为 。
{{ select(23) }}
- 正确
- 错误
- 下面的贪心代码一定能对任意硬币面值集合 coins 求出 money 所需的最少硬币数。
int count = 0;
for (int coin : coins) { // coins 按面值从大到小排列
count += money / coin;
money %= coin;
}
{{ select(24) }}
- 正确
- 错误
- 假设两个非负高精度整数分别存储在数组 a 和 b 中,且 。数组采用低位在前的方式存储,即a[0] 表示个位。下面代码中的 c 可以正确保存 a - b 的各位数字。
int borrow = 0;
for (int i = 0; i < len; ++i) {
int t = a[i] - b[i] + borrow;
if (t < 0) {
t += 10;
borrow = 1;
} else {
borrow = 0;
}
c[i] = t;
}
{{ select(25) }}
- 正确
- 错误