习题均来自B站up:白话拆解数据结构!
今日习题如下:
(1)从有序顺序表中删除给定值s到t范围的元素
(2)将两个有序顺序表合并为一个新的有序顺序表,并返回这个新的顺序表
第一题
和day2的第二题很像,就是比那题多了个有序的条件。所以可以沿用那天的思路,无序都能做,有序不是更简单。
法一:和day2一样,将不属于这之间的元素插入到“新表”中
bool del_s_t(SqList &L,int s,int t){
if(L.length==0||s>=t) return false;
int j=0; // 记录被删除的个数
for(int i =0;i<L.length;i++)
{
if(L.data[i]<s || L.data[i]>t )
{
L.data[j]=L.data[i]; //和day3一样的思想,j表示的是“新表”的位置
j++;
}
}
L.length = j;//无需修正位序,由于j++的关系,循环结束后会自己加1
return true;
}
法二:其实就是法一的改进,法一算是一个暴力解法,当s和t在表很后的位置时,会多出来很多无效的比较次数。而这个表是有序表,所以我们只需要找到第一个大于或者等于s的元素和第一个大于t的元素,标记一下这个两个元素,这俩元素中间的不就是我们要删除的值了吗?将后面的元素整体向前覆盖即可!
bool del_(SqList &L,int s,int t){
if(L.length==0||s>=t) return false;
int i,j;
for(i=0;i<L.length;i++) //找s
if(L.data[i]>=s) break;
for(j=0;j<L.length;j++) //找t
if(L.data[j]>t) break;
printf("%d %d",i,j); // 记录一下找到的下标
cout << endl;
for(int m=j;m<L.length;m++) // 整体前移
L.data[i++]=L.data[j++];
L.length=L.length-(j-i); // 更新表长
return true;
}
证一下:(由于表是随机赋值的,所以调用了一下sort函数来满足题目)
删除的范围是3到6:成功
再试一次:成功!
完整代码如下:(在vscode环境下成功跑通)
#include <iostream>
#include <cstdio>
#include <ctime>
#include<algorithm>
using namespace std;
// 从有序顺序表中删除给定值s到t范围的元素
typedef int ElemType;
struct SqList {
ElemType data[100];
int length;
};
// 法一:完全可以用day4的方法
bool del_s_t(SqList &L,int s,int t){
if(L.length==0||s>=t) return false;
int j=0; // 记录被删除的个数
for(int i =0;i<L.length;i++)
{
if(L.data[i]<s || L.data[i]>t )
{
L.data[j]=L.data[i]; //和day3一样的思想,j表示的是“新表”的位置
j++;
}
}
L.length = j;//无需修正位序,由于j++的关系,循环结束后会自己加1
return true;
}
// 法二:有序表的元素是排好的,只需要找到第一个大于或等于s和第一个大于t的下标即可
bool del_(SqList &L,int s,int t){
if(L.length==0||s>=t) return false;
int i,j;
for(i=0;i<L.length;i++) //找s
if(L.data[i]>=s) break;
for(j=0;j<L.length;j++) //找t
if(L.data[j]>t) break;
printf("%d %d",i,j);
cout << endl;
for(int m=j;m<L.length;m++)
L.data[i++]=L.data[j++];
L.length=L.length-(j-i);
return true;
}
int main() {
SqList L;
L.length =15;
srand(static_cast<unsigned int>(time(nullptr)));
// 随机赋值
for(int i =0;i<L.length;i++){
L.data[i] = rand()%10;
}
cout << "Original list: ";
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
sort(L.data,L.data+L.length);
cout << "sorted list: ";
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
if (del_(L, 3,6)) {
cout << "The new list is: ";
for (int i = 0; i < L.length; i++) {
cout << L.data[i] << " ";
}
cout << endl;
} else {
cout << "The list is empty." << endl;
}
return 0;
}
题二
法一:将这两个表加进一个数组里,再用快速排序排一遍!空间复杂度O(n),时间复杂度为O(nlogn),这里的n表示两个表的总长度。
法二:答案的做法,开辟一个新数组,循环遍历表1,表2元素,两两比较,小者存入结果表,重复元素也可放置;当一个表放完了,另一个表剩下的部分全部追加到表尾即可!
我懒得敲了,直接放答案,答案做法时间复杂度O(max(A,B)),空间复杂度是O(A+B)。
法三:我自己的做法。时间复杂度为O(n1^2),n1为表1长度,空间复杂度为O(1)。
先将表1扩充,就是改变它的length。然后就是插入的思想,将L2中比L1小的元素插入进去,如果L2还有剩余,就把整个L2表加到L1表后面。
bool merge_(SqList &L1,SqList &L2)
{
if(L1.length==0||L2.length==0) return false;
int i=L1.length,j=0,temp;
L1.length += L2.length; // 扩充表长
for(int m=0;m<i;m++)
{
if(L1.data[m]>=L2.data[j])
{
for(int n = 0;n<i-m;n++) //元素后移
{
L1.data[i-n] = L1.data[i-n-1];
}
L1.data[m]=L2.data[j]; // 插入进去
i++;
j++;
}
}
if(j<L2.length)
for(;j<L2.length;j++)
L1.data[i++]=L2.data[j];
return true;
}
证一下:成功!
完整代码如下:(在vscode环境下已成功跑通)
#include <iostream>
#include <cstdio>
#include <ctime>
#include<algorithm>
using namespace std;
// 将两个有序顺序表合并为一个新的有序顺序表,并返回这个新的顺序表
typedef int ElemType;
struct SqList {
ElemType data[100];
int length;
};
//插入的思想,将L2中比L1小的元素插入进去,如果L2还有剩余,就把整个L2表加到L1表后面
bool merge_(SqList &L1,SqList &L2)
{
if(L1.length==0||L2.length==0) return false;
int i=L1.length,j=0,temp;
L1.length += L2.length;
// for(i;i<L1.length;i++)
// L1.data[i]=L2.data[j++];
for(int m=0;m<i;m++)
{
if(L1.data[m]>=L2.data[j])
{
for(int n = 0;n<i-m;n++)
{
L1.data[i-n] = L1.data[i-n-1];
}
L1.data[m]=L2.data[j];
i++;
j++;
}
}
if(j<L2.length)
for(;j<L2.length;j++)
L1.data[i++]=L2.data[j];
return true;
}
int main() {
SqList L1,L2;
L1.length =5;
L2.length = 4;
srand(static_cast<unsigned int>(time(nullptr)));
// 随机赋值
for(int i =0;i<L1.length;i++){
L1.data[i] = rand()%10;
}
sort(L1.data,L1.data+L1.length);
cout << "sorted list L1: ";
for (int i = 0; i < L1.length; i++) {
cout << L1.data[i] << " ";
}
cout << endl;
for(int i =0;i<L2.length;i++){
L2.data[i] = rand()%10;
}
// cout << "Original list L2: ";
// for (int i = 0; i < L2.length; i++) {
// cout << L2.data[i] << " ";
// }
// cout << endl;
sort(L2.data,L2.data+L2.length);
cout << "sorted list L2: ";
for (int i = 0; i < L2.length; i++) {
cout << L2.data[i] << " ";
}
cout << endl;
if (merge_(L1, L2)) {
cout << "The new list is: ";
for (int i = 0; i < L1.length; i++) {
cout << L1.data[i] << " ";
}
cout << endl;
} else {
cout << "The list is empty." << endl;
}
return 0;
}