今日题目来自B站up:白话拆解数据结构!
题目如下:
1、已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,...,am)和(b1,b2,...,bn),编写一个函数,将数组中两个顺序表互换,即将(b1,b2,...,bn)放在(a1,a2,...,am)的前面。
2、【全国统考2010】设将n(n>1)个整数存放到一维数组R中。试设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数组由(X0,X1, … Xn-1)变换为(Xp,Xp-1, … Xn-1,X0,X1, … Xp-1)。要求:
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C、C++或JAVA语言描述算法,关键之处给出注释。
(3)说明你所涉及算法的时间复杂度和空间复杂度。
题一:
感觉题目有点小瑕疵,如果是数组里存两个线性表,由于线性表的结构体有个length域,实际上是这么个情况:
一是A[m+n]空间不够存,而是要跳开length来存比较麻烦。
对题目进行小修改: 在线性表A中依次存放两个数组,其它不变。或者干脆就全改成数组也行。
法一:申请一个临时数组B,大小是两个数组的长度之和;将表A的后n部分整体赋值给B数组的前面,再将表A的前m部分整体赋值给B数组的后面;最后将B数组的值再还给表A即可!
bool new_array(SqList &L,int m,int n){
if(L.length==0) return false;
int B[m+n];
for(int i=m,j=0;i<L.length;i++,j++) //表的后n部分整体赋值给B数组的前面
B[j] = L.data[i];
for(int i=0,j=n;i<m;i++,j++) // 表的前m部分整体赋值给B数组的后面
B[j] = L.data[i];
// 将B数组的值整体赋值给表
for(int i=0,j=0;i<L.length;i++,j++)
L.data[i]=B[j];
return true;
}
法二:这个不太好想。先将表A的前m部分逆置,再将表A的后n部分逆置,最后将表A整体逆置。
注意第二个循环的条件要加上m进行补足,因为i是从m开始的!
void swap_elem(SqList &L, int i, int j){
int tmp = L.data[i];
L.data[i] = L.data[j];
L.data[j] = tmp;
}
bool reverse_list(SqList &L,int m,int n){
if(L.length==0) return false;
for(int i=0,j=m-1;i<m/2;i++,j--) // 前m部分逆置
swap_elem(L,i,j);
for(int i=m,j=L.length-1;i<m+n/2;i++,j--) // 后n部分逆置
swap_elem(L,i,j);
for(int i=0,j=L.length-1;i<L.length/2;i++,j--) // 整体逆置
swap_elem(L,i,j);
return true;
}
看看结果把:m=3,n=7
再来试试m=6,n=4
over!完整代码如下:(在vscode环境下已成功跑通)
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
// 一维数组A[m+n]中存了俩表a[m]和b[n]。要求编写一个函数将这两个顺序表位置互换
struct SqList{
int data[100];
int length;
};
// 法一:申请一个临时数组
bool new_array(SqList &L,int m,int n){
if(L.length==0) return false;
int B[m+n];
for(int i=m,j=0;i<L.length;i++,j++) //表的后n部分整体赋值给B数组的前面
B[j] = L.data[i];
for(int i=0,j=n;i<m;i++,j++) // 表的前m部分整体赋值给B数组的后面
B[j] = L.data[i];
// 将B数组的值整体赋值给表
for(int i=0,j=0;i<L.length;i++,j++)
L.data[i]=B[j];
return true;
}
// 法二:先将a数组逆置,再将b数组逆置,最后整体逆置
void swap_elem(SqList &L, int i, int j){
int tmp = L.data[i];
L.data[i] = L.data[j];
L.data[j] = tmp;
}
bool reverse_list(SqList &L,int m,int n){
if(L.length==0) return false;
for(int i=0,j=m-1;i<m/2;i++,j--)
swap_elem(L,i,j);
for(int i=m,j=L.length-1;i<m+n/2;i++,j--)
swap_elem(L,i,j);
for(int i=0,j=L.length-1;i<L.length/2;i++,j--)
swap_elem(L,i,j);
return true;
}
int main() {
SqList L;
L.length =10;
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;
if (reverse_list(L, 6,4)) {
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;
}
题二:这题和题一几乎一致
法一:新建个临时数组,前p个元素放到数组后面,后n-p个元素放到数组前面
bool zuoyi(int R[],int p,int n){
int m[n];
for(int i=p,j=0;i<n;i++,j++)
m[j]=R[i];
for(int i=0,j=n-p;i<p;i++,j++)
m[j]=R[i];
for(int i=0,j=0;i<n;i++,j++)
R[i]=m[j];
return true;
}
时间复杂度为O(n),空间复杂度为O(n)
法二: 和上题一样逆置的思想,前p个逆置,后n-p个逆置,再整体逆置。因为其实就是前p个数组和后n-p个数组调换位置而已!
void swap_elem(int a[], int i, int j){
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
bool reverse_list(int a[],int p,int n){
for(int i=0,j=p-1;i<p/2;i++,j--)
swap_elem(a,i,j);
for(int i=p,j=n-1;i<p+(n-p+1)/2;i++,j--) // 注意这里的判断条件
swap_elem(a,i,j);
for(int i=0,j=n-1;i<n/2;i++,j--)
swap_elem(a,i,j);
return true;
}
时间复杂度为O(n/2),空间复杂度O(1)。高效
试试结果:p=3,n=10(这里的n是数组长度)
p=6,n=10
over!完整代码如下:
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
// 将n个整数存放到一维数组R中,设计一个尽可能高效的算法,将R中保存的序列循环左移P(0<p<n)个位置
// 法一:新建个临时数组,前p个元素放到数组后面,后n-p个元素放到数组前面
bool zuoyi(int R[],int p,int n){
int m[n];
for(int i=p,j=0;i<n;i++,j++)
m[j]=R[i];
for(int i=0,j=n-p;i<p;i++,j++)
m[j]=R[i];
for(int i=0,j=0;i<n;i++,j++)
R[i]=m[j];
return true;
}
// 法二:和题一一样逆置的思想,前p个逆置,后n-p个逆置,再整体逆置
void swap_elem(int a[], int i, int j){
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
bool reverse_list(int a[],int p,int n){
for(int i=0,j=p-1;i<p/2;i++,j--)
swap_elem(a,i,j);
for(int i=p,j=n-1;i<p+(n-p+1)/2;i++,j--)
swap_elem(a,i,j);
for(int i=0,j=n-1;i<n/2;i++,j--)
swap_elem(a,i,j);
return true;
}
int main() {
int a[10];
srand(static_cast<unsigned int>(time(nullptr)));
// 随机赋值
for(int i =0;i<10;i++){
a[i] = rand()%10;
}
cout << "Original array: ";
for (int i = 0; i < 10; i++) {
cout << a[i] << " ";
}
cout << endl;
if (reverse_list(a, 6,10)) {
cout << "The new arry is: ";
for (int i = 0; i < 10; i++) {
cout << a[i] << " ";
}
cout << endl;
} else {
cout << "The list is empty." << endl;
}
return 0;
}