一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
计划更新23王道数据结构所有课后代码习题的实现,虽然考试写的一般都是伪代码,但是强迫症的我还是全部实现了一遍,仓库在这里
- 线性表
2.2.3, 10
- 这个真题跟第8题基本一样,我们可以直接copy过来改一下参数
- 首先就是暴力求解,新开一个数组,分别复制进去(把结构体改成数组是一样的)
- 这样的时间复杂度是O(n),空间复杂度也是O(n)
- 为了节省空间,也可以创建一个大小为p的数组暂存前一个数组[0, p-1],原数组整体左移后再依次放回,这样的空间复杂度会降到O(p)
void change(SqList &list, int p, int n) {
// 1.左右两个数组分别是[0, p-1], [p, n-1]
SqList copied = list;
int k = -1;
// 2.分别复制进去
for (int i = p; i < n; i++) {
copied.data[++k] = list.data[i];
}
for (int i = 0; i < p; i++) {
copied.data[++k] = list.data[i];
}
// 3.新换旧
list = copied;
}
复制代码
- 四两拨千斤,整体逆置,再分别逆置
- 比如说[1, 2, 3, 4]逆置成[4, 3, 2, 1],然后其中一个数组[4, 3]逆置成[3, 4],另一个[2, 1]逆置成[1, 2],最后结果就是[3, 4, 1, 2]
- 时间复杂度O(n),空间复杂度O(1)
void reverse(SqList &list, int l, int r) {
if (l > r || r > list.length) return;
for (int i = 0; i < (r-l+1)/2 ; i++) {
swap(list.data[l+i], list.data[r-i]);
}
}
void change2(SqList &list, int p, int n) {
// 注意参数
reverse(list, 0, n);
reverse(list, 0, p);
reverse(list, p, n);
}
复制代码
2.2.3, 11
- 找到两个有序序列合并后的中位数,那暴力解就直接合并呗
- 可以把第7题直接抄过来,然后返回
(A.length + B.length)/2
位置上的数即可 - 然后你会发现并不需要合并全部,也不需要一个辅助表来存储数据,只需要循环到这个位置就可以了
- 注意题目中要求,mid 应该等于
(A.length + B.length - 1) / 2
- 时间复杂度O(n),空间复杂度O(1)
int merge(SqList A, SqList B) {
int i = 0, j = 0, k = -1, mid = (A.length + B.length - 1) / 2;
// 条件也不需要,因为我们找到中间值就会直接return
while (1) {
++k;
if (A.data[i] <= B.data[j]) {
if (k == mid) return A.data[i];
i++;
} else {
if (k == mid) return B.data[j];
j++;
}
}
}
复制代码
- 也可以直接循环到 mid 处,不需要每次都判断一次
==mid
int merge2(SqList A, SqList B) {
int i = 0, j = 0, mid = (A.length + B.length - 1) / 2 ;
while (i+j < mid) {
if (A.data[i] <= B.data[j]) i++;
else j++;
}
return A.data[i] < B.data[j] ? A.data[i] : B.data[j];
}
复制代码
- 考试不建议最优解,时间成本太高(大佬除外),毕竟暴力解最多好像只有5分差距,没必要
- 我这里就不写了,可以看一下王道答案