以下应用题全部来自2021版王道应用题
设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)
算法思想:一开始我都没仔细读题 还纳闷时间复杂度为O(1) 这怎么想呢 跟链表一样吗 设计一个头指针与尾指针 他俩调换就行了?后来一看题才是空间复杂度 这才是我们所熟悉的题
L->data[L->last-i] = L->data[i] 从前往后一直循环到 last/2 跳出 具体代码如下:
int myreverse(sequenlist *L){
for (int i=0; i<=L->last/2; i++) {
datatype temp = L->data[L->last-i];
L->data[L->last-i] = L->data[i];
L->data[i] = temp;
}
return 1;
}
分
割
线
对长度为n的顺序表L,编写一个时间复杂度为O(n)、空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素
如果我们还用上节课所学的知识来写代码话 我们会先遍历找到第一个x然后实现删除操作 全部都向前平移 平移完再找到第二个然后再平移 显然 时间复杂度为O(n2) 那么怎么实现O(n)呢 这里我们就需要引入一个变量 k 来记录第i个元素前 有多少个重复的元素 注意是变量k 对于不同的元素 k的值是不同的 让我们来看具体代码:
int FindAllXtodelete(sequenlist *L,datatype x){
int k=0; //作为x的个数
for (int i=0; i<=L->last; i++) {
if (L->data[i] == x) {
k++;
}
else
L->data[i-k] = L->data[i]; //向前移动k个单位
}
L->last = L->last-k
return 1;
}
分
割
线
从顺序表中删除其值在给定值s与t之间(s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出运行
算法思想 其实本题与上一题思想相同 就是if条件发生了改变 让我们具体看一下代码
int Delete_s_t(sequenlist *L,datatype s,datatype t){
if (s>=t||L->last+1<=0) {
printf("error");
return 0;
}
int i;
int k=0;
for ( i=0; i<=L->last; i++) {
if(L->data[i]>=s&&L->data[i]<=t)
k++;
else
L->data[i-k] = L->data[i];
}
L->last = i;
return 1;
}
分
割
线
从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同
思想:让我们回顾直接插入排序 让我们复制一个顺序表取第j个元素与顺序表最后一个元素相比 若相同j++ 若不同就可以在i后面插入元素了 需要我们思考的是i后面那个元素位置怎么表示呢 最后 i也就是我们L->last的值 L->last指向下标呦
让我们来看下代码:
int DeleteOrderlySequence(sequenlist *L){
if (L->last+1<=0) {
printf("error");
return 0;
}
int i,j; //i存储第一个不相同的元素 j为工作指针
for (i=0,j=1; j<=L->last; j++) {
if (L->data[i]!=L->data[j]) {
i++;
L->data[i] = L->data[j];
//以上两行代码也能简写成 L->data[++i] = L->data[j];
//注意 ++i 与i++ 他们俩是有区别 下个题你就能看到i++ 了
}
}
L->last = i;
return 1;
}
分
割
线
将两个有序顺序表合并成一个新的有序顺序表,并由函数返回结果顺序表
思想:首先就是在创建一个顺序表 表长等于那两个表加起来 三个表相对应的那肯定有三个变量 i,j,k来表示他们的下标 判断条件 两个表里的元素谁小 就把谁放在新表里 新表下标加1 小的那个表下标也加1 总有一个表先放完 一个表后放完 一个表放完后 跳出循环 直接把第二个表剩下的元素放进新表就OK了 代码如下:
int MergerOrderlySequence(sequnelist *L,sequnelist *L1,sequnelist *L2){
int i,j,k;
if (L1->last+L12->last+1>L->last) {
printf("error");
return 0;
}
while ((L1->last+1)--&&(L2->last+1)--) {
if (L1->data[i]<=L2->data[j]) {
L->data[k++] = L1->data[i++]; //先赋值再自增 ☆
}
else
L->data[k++] = L2->data[j++];
}
while (i<=L1->last) {
L->data[k++] = L1->data[i++];
}
while (j<=L2->last) {
L->data[k++] = L1->data[j++];
}
L->last=k-1; // 程序结束前 k还是会执行自增操作 所以k代表着顺序表的长度 k-1才是下标
}