顺序表应用1:多余元素删除之移位算法
Time Limit: 1000MS Memory Limit: 650KB
Problem Description
一个长度不超过10000数据的顺序表,可能存在着一些值相同的“多余”数据元素(类型为整型),编写一个程序将“多余”的数据元素从顺序表中删除,使该表由一个“非纯表”(值相同的元素在表中可能有多个)变成一个“纯表”(值相同的元素在表中只保留第一个)。
要求:
1、必须先定义线性表的结构与操作函数,在主函数中借助该定义与操作函数调用实现问题功能;
2、本题的目标是熟悉顺序表的移位算法,因此题目必须要用元素的移位实现删除;
Input
第一行输入整数n,代表下面有n行输入;
之后输入n行,每行先输入整数m,之后输入m个数据,代表对应顺序表的每个元素。
Output
输出有n行,为每个顺序表删除多余元素后的结果
Example Input
4
5 6 9 6 8 9
3 5 5 5
5 9 8 7 6 5
10 1 2 3 4 5 5 4 2 1 3
Example Output
6 9 8
5
9 8 7 6 5
1 2 3 4 5
Hint
Author
以下为Accepted代码1——结构体
#include
using namespace std;
struct Table{
int size;
int *num;
};
void Build(Table &a, int n);/*建表*/
void move_num(Table &a);/*移位算法删除重复元素*/
void pri_num(Table &a);/*输出删除重复元素之后的序列*/
int main(){
int T, n;
Table a;/*定义表a*/
cin >> T;
while(T--){
cin >> n;
Build(a, n);
move_num(a);
pri_num(a);
}
return 0;
}
void Build(Table &a, int n){
a.size = n;
a.num = new int[11400];
for(int i = 0; i < n; i++)
cin >> a.num[i];
}
void move_num(Table &a){
for(int i = 0; i < a.size; i++){
int j = i + 1;
while(j < a.size){
if(a.num[i] != a.num[j])
j++;
else {
for(int k = j; k < a.size-1; k++)
a.num[k] = a.num[k+1];
a.size--;
}
}
}
}
void pri_num(Table &a){
for(int i = 0; i < a.size; i++){
cout << a.num[i];
i == a.size-1? cout << '\n': cout << ' ';
}
delete []a.num;
}
/*************************************************** User name: Result: Accepted Take time: 44ms Take Memory: 244KB Submit time: 2017-09-15 16:53:15 ****************************************************/
以下为Accepted代码2——C++类
#include
using namespace std;
class Table{
private:
int size;
int *num;
public:
void build_table(int n);
void move_num();
void pri_num();
void delete_memory();
};
void Table::build_table(int n){
size = n;
num = new int[n+4];
for(int i = 0; i < n; i++)
cin >> num[i];
}
void Table::move_num(){
for(int i = 0; i < size; i++){
int j = i + 1;
while(j < size){
if(num[i] != num[j])
j++;
else {
for(int k = j; k < size-1; k++)
num[k] = num[k+1];
size--;
}
}
}
}
void Table::pri_num(){
for(int i = 0; i < size; i++){
cout << num[i];
i == size-1? cout << '\n': cout << ' ';
}
}
void Table::delete_memory(){
delete []num;
}
int main(){
int T, n;
Table test;
cin >> T;
while(T--){
cin >> n;
test.build_table(n);
test.move_num();
test.pri_num();
test.delete_memory();
}
return 0;
}
/*************************************************** User name: Result: Accepted Take time: 44ms Take Memory: 244KB Submit time: 2017-09-15 17:06:33 ****************************************************/
顺序表应用2:多余元素删除之建表算法
Time Limit: 3MS Memory Limit: 600KB
Problem Description
一个长度不超过10000数据的顺序表,可能存在着一些值相同的“多余”数据元素(类型为整型),编写一个程序将“多余”的数据元素从顺序表中删除,使该表由一个“非纯表”(值相同的元素在表中可能有多个)变成一个“纯表”(值相同的元素在表中只保留第一个)。
要求:
1、必须先定义线性表的结构与操作函数,在主函数中借助该定义与操作函数调用实现问题功能;
2、本题的目标是熟悉在顺序表原表空间基础上建新表的算法,要在原顺序表空间的基础上完成完成删除,建表过程不得开辟新的表空间;
3、不得采用原表元素移位删除的方式。
Input
第一行输入整数n,代表下面有n行输入;
之后输入n行,每行先输入整数m,之后输入m个数据,代表对应顺序表的每个元素。
Output
输出有n行,为每个顺序表删除多余元素后的结果
Example Input
4
5 6 9 6 8 9
3 5 5 5
5 9 8 7 6 5
10 1 2 3 4 5 5 4 2 1 3
Example Output
6 9 8
5
9 8 7 6 5
1 2 3 4 5
Hint
Author
以下为Accepted代码
#include
using namespace std;
struct Table{
int size;
int *num;
};
void build_table(Table &a, int n);/*建表*/
void rebuild_table(Table &a);/*通过表的重建删除重复元素*/
void pri_table(Table &a);/*输出新表(去除重复元素之后的序列)*/
void delete_memory(Table &a);/*释放内存*/
int main(){
int T, n;
Table a;
cin >> T;
while(T--){
cin >> n;
build_table(a, n);
rebuild_table(a);
pri_table(a);
delete_memory(a);
}
return 0;
}
void build_table(Table &a, int n){
a.size = n;
a.num = new int[n+4];
for(int i = 0; i < n; i++)
cin >> a.num[i];
}
void rebuild_table(Table &a){
int i, j, k = 0;
for(i = 0; i < a.size; i++){
for(j = 0; j < k; j++){
if(a.num[j] == a.num[i])
break;
}
if(k == 0 || j == k)
a.num[k++] = a.num[i];
}
a.size = k;
}
void pri_table(Table &a){
for(int i = 0; i < a.size; i++){
cout << a.num[i];
i == a.size-1? cout << '\n': cout << ' ';
}
}
void delete_memory(Table &a){
delete []a.num;
}
/*************************************************** User name: Result: Accepted Take time: 4ms Take Memory: 264KB Submit time: 2017-09-15 17:29:35 ****************************************************/
顺序表应用3:元素位置互换之移位算法
Time Limit: 1000MS Memory Limit: 570KB
Problem Description
一个长度为len(1<=len<=1000000)的顺序表,数据元素的类型为整型,将该表分成两半,前一半有m个元素,后一半有len-m个元素(1<=m<=len),借助元素移位的方式,设计一个空间复杂度为O(1)的算法,改变原来的顺序表,把顺序表中原来在前的m个元素放到表的后段,后len-m个元素放到表的前段。
注意:先将顺序表元素调整为符合要求的内容后,再做输出,输出过程只能用一个循环语句实现,不能分成两个部分。
Input
第一行输入整数n,代表下面有n行输入;
之后输入n行,每行先输入整数len与整数m(分别代表本表的元素总数与前半表的元素个数),之后输入len个整数,代表对应顺序表的每个元素。
Output
输出有n行,为每个顺序表前m个元素与后(len-m)个元素交换后的结果
Example Input
2
10 3 1 2 3 4 5 6 7 8 9 10
5 3 10 30 20 50 80
Example Output
4 5 6 7 8 9 10 1 2 3
50 80 10 30 20
Hint
注意:先将顺序表元素调整为符合要求的内容后,再做输出,输出过程只能在一次循环中完成,不能分成两个部分输出。
Author
以下为Accepted代码
#include
using namespace std;
struct Table{
int len, m;
int *num;
};
void build_table(Table &a, int len, int m);/*建表*/
void rebuild_table(Table &a);/*调整序列*/
void swap_num(Table &a, int l, int r);/*交换数组a.num中区间[l, r]的数*/
void pri_num(Table &a);/*输出序列中的数*/
void delete_memory(Table &a);/*释放内存*/
int main(){
int T, len, m;
Table test;
cin >> T;
while(T--){
cin >> len >> m;
build_table(test, len, m);
rebuild_table(test);
pri_num(test);
delete_memory(test);
}
return 0;
}
void build_table(Table &a, int len, int m){
a.len = len, a.m = m;
a.num = new int[len+4];
for(int i = 1; i <= len; i++)
cin >> a.num[i];
}
void rebuild_table(Table &a){
swap_num(a, 1, a.m);
swap_num(a, a.m+1, a.len);
swap_num(a, 1, a.len);
}
void swap_num(Table &a, int l, int r){
int t, mid = (l+r)/2;
for(int i = l; i <= mid; i++){
t = a.num[i], a.num[i] = a.num[l+r-i], a.num[l+r-i] = t;
}
}
void pri_num(Table &a){
for(int i = 1; i <= a.len; i++){
cout << a.num[i];
i == a.len? cout << '\n': cout << ' ';
}
}
void delete_memory(Table &a){
delete []a.num;
}
/*************************************************** User name: Result: Accepted Take time: 8ms Take Memory: 244KB Submit time: 2017-09-15 17:51:39 ****************************************************/
顺序表应用4-2:元素位置互换之逆置算法(数据改进)
Time Limit: 80MS Memory Limit: 600KB
Problem Description
一个长度为len(1<=len<=1000000)的顺序表,数据元素的类型为整型,将该表分成两半,前一半有m个元素,后一半有len-m个元素(1<=m<=len),设计一个时间复杂度为O(N)、空间复杂度为O(1)的算法,改变原来的顺序表,把顺序表中原来在前的m个元素放到表的后段,后len-m个元素放到表的前段。
注意:交换操作会有多次,每次交换都是在上次交换完成后的顺序表中进行。
Input
第一行输入整数len(1<=len<=1000000),表示顺序表元素的总数;
第二行输入len个整数,作为表里依次存放的数据元素;
第三行输入整数t(1<=t<=30),表示之后要完成t次交换,每次均是在上次交换完成后的顺序表基础上实现新的交换;
之后t行,每行输入一个整数m(1<=m<=len),代表本次交换要以上次交换完成后的顺序表为基础,实现前m个元素与后len-m个元素的交换;
Output
输出一共t行,每行依次输出本次交换完成后顺序表里所有元素。
Example Input
10
1 2 3 4 5 6 7 8 9 -1
3
2
3
5
Example Output
3 4 5 6 7 8 9 -1 1 2
6 7 8 9 -1 1 2 3 4 5
1 2 3 4 5 6 7 8 9 -1
Hint
Author
以下为Accepted代码
#include
#include
#include
using namespace std;
struct Table{
int len;
int *num;
};
void build_table(Table &a, int len);/*建表*/
void rebuild_table(Table &a, int m);/*移位互换*/
void swap_num(Table &a, int l, int r);/*将数组a.num在区间[l, r]的数转置*/
void pri_num(Table &a);/*输出当前状态的序列*/
void delete_memory(Table &a);/*释放内存*/
int main(){
int len, T, m;
Table test;
while(~scanf("%d", &len)){
build_table(test, len);
scanf("%d", &T);
while(T--){
scanf("%d", &m);
rebuild_table(test, m);
pri_num(test);
}
delete_memory(test);
}
return 0;
}
void build_table(Table &a, int len){
a.len = len;
a.num = new int[len+4];
for(int i = 1; i <= len; i++)
scanf("%d", &a.num[i]);
}
void rebuild_table(Table &a, int m){
swap_num(a, 1, m);
swap_num(a, m+1, a.len);
swap_num(a, 1, a.len);
}
void swap_num(Table &a, int l, int r){
int t, mid = (l+r)/2;
for(int i = l; i <= mid; i++){
t = a.num[i], a.num[i] = a.num[r+l-i], a.num[r+l-i] = t;
}
}
void pri_num(Table &a){
for(int i = 1; i <= a.len; i++){
printf("%d%c", a.num[i], i == a.len? '\n': ' ');
}
}
void delete_memory(Table &a){
delete []a.num;
}
/*************************************************** User name: Result: Accepted Take time: 80ms Take Memory: 556KB Submit time: 2017-09-15 21:53:37 ****************************************************/
顺序表应用5:有序顺序表归并
Time Limit: 100MS Memory Limit: 880KB
Problem Description
已知顺序表A与B是两个有序的顺序表,其中存放的数据元素皆为普通整型,将A与B表归并为C表,要求C表包含了A、B表里所有元素,并且C表仍然保持有序。
Input
输入分为三行:
第一行输入m、n(1<=m,n<=10000)的值,即为表A、B的元素个数;
第二行输入m个有序的整数,即为表A的每一个元素;
第三行输入n个有序的整数,即为表B的每一个元素;
Output
输出为一行,即将表A、B合并为表C后,依次输出表C所存放的元素。
Example Input
5 3
1 3 5 6 9
2 4 10
Example Output
1 2 3 4 5 6 9 10
Hint
Author
以下为Accepted代码
#include
using namespace std;
struct Table{
int size;
int *num;
};
void build_table(Table &a, int len);
Table union_table(Table &a, Table &b);
void pri_table(Table &a);
void delete_table(Table &a);
int main(){
int m, n;
Table a, b, c;
while(cin >> m >> n){
build_table(a, m);
build_table(b, n);
c = union_table(a, b);
pri_table(c);
delete_table(a);
delete_table(b);
delete_table(c);
}
return 0;
}
void build_table(Table &a, int len){
a.size = len;
a.num = new int[len+4];
for(int i = 0; i < len; i++)
cin >> a.num[i];
}
Table union_table(Table &a, Table &b){
Table c;
c.size = a.size + b.size;
c.num = new int[c.size+4];
int i = 0, j = 0, k = 0;
while(i < a.size && j < b.size){
if(a.num[i] < b.num[j]){
c.num[k++] = a.num[i];
i++;
}
else {
c.num[k++] = b.num[j];
j++;
}
}
while(i < a.size){
c.num[k++] = a.num[i];
i++;
}
while(j < b.size){
c.num[k++] = b.num[j];
j++;
}
return c;
}
void pri_table(Table &a){
for(int i = 0; i < a.size; i++){
cout << a.num[i];
i == a.size-1? cout << '\n': cout << ' ';
}
}
void delete_table(Table &a){
delete []a.num;
}
/*************************************************** User name: Result: Accepted Take time: 16ms Take Memory: 356KB Submit time: 2017-09-15 22:04:04 ****************************************************/
顺序表应用6:有序顺序表查询
Time Limit: 1000MS Memory Limit: 4096KB
Problem Description
顺序表内按照由小到大的次序存放着n个互不相同的整数,任意输入一个整数,判断该整数在顺序表中是否存在。如果在顺序表中存在该整数,输出其在表中的序号;否则输出“No Found!”。
Input
第一行输入整数n (1 <= n <= 100000),表示顺序表的元素个数;
第二行依次输入n个各不相同的有序非负整数,代表表里的元素;
第三行输入整数t (1 <= t <= 100000),代表要查询的次数;
第四行依次输入t个非负整数,代表每次要查询的数值。
保证所有输入的数都在 int 范围内。
Output
输出t行,代表t次查询的结果,如果找到在本行输出该元素在表中的位置,否则本行输出No Found!
Example Input
10
1 22 33 55 63 70 74 79 80 87
4
55 10 2 87
Example Output
4
No Found!
No Found!
10
Hint
Author
#include
#include
#include
using namespace std;
struct Table{
int size;
int *num;
};
void build_table(Table &L, int n);/*建表*/
void search_x(Table L, int x);/*二分查找*/
void delete_table(Table &L);/*释放内存*/
int main(){
int n, q, x;
Table test;
while(~scanf("%d", &n)){
build_table(test, n);
scanf("%d", &q);
while(q--){
scanf("%d", &x);
search_x(test, x);
}
delete_table(test);
}
return 0;
}
void build_table(Table &L, int n){
L.size = n;
L.num = new int[n+4];
for(int i = 1; i <= n; i++)
scanf("%d", &L.num[i]);
}
void search_x(Table L, int x){
int l, r, mid;
l = 1, r = L.size;
while(l <= r){
mid = (l+r)>>1;
if(L.num[mid] == x){
printf("%d\n", mid);
return;
}
else if(L.num[mid] > x){
r = mid-1;
}
else if(L.num[mid] < x){
l = mid + 1;
}
}
printf("No Found!\n");
return;
}
void delete_table(Table &L){
delete []L.num;
}
/*************************************************** User name: Result: Accepted Take time: 60ms Take Memory: 508KB Submit time: 2017-09-20 20:47:20 ****************************************************/
顺序表应用7:最大子段和之分治递归法
Time Limit: 10MS Memory Limit: 400KB
Problem Description
给定n(1<=n<=50000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
注意:本题目要求用分治递归法求解,除了需要输出最大子段和的值之外,还需要输出求得该结果所需的递归调用总次数。
递归调用总次数的获得,可以参考以下求菲波那切数列的代码段中全局变量count的用法:
#include
int count=0;
int main()
{
int n,m;
int fib(int n);
scanf("%d",&n);
m=fib(n);
printf("%d %d\n",m,count);
return 0;
}
int fib(int n)
{
int s;
count++;
if((n==1)||(n==0)) return 1;
else s=fib(n-1)+fib(n-2);
return s;
}
Input
第一行输入整数n(1<=n<=50000),表示整数序列中的数据元素个数;
第二行依次输入n个整数,对应顺序表中存放的每个数据元素值。
Output
一行输出两个整数,之间以空格间隔输出:
第一个整数为所求的最大子段和;
第二个整数为用分治递归法求解最大子段和时,递归函数被调用的总次数。
Example Input
6
-2 11 -4 13 -5 -2
Example Output
20 11
Hint
Author
以下为Accepted代码
#include
#include
#include
using namespace std;
struct Table{
int size;
int *num;
};
int cnt;
void build_table(Table &L, int n);/*建表*/
int max_sum(Table L, int l, int r);/*分治递归法求解最大子段和*/
void delete_table(Table &L);/*释放内存*/
int main(){
int n, ans;
Table test;
while(~scanf("%d", &n)){
cnt = 0;
build_table(test, n);
ans = max_sum(test, 1, n);
printf("%d %d\n", ans, cnt);
delete_table(test);
}
return 0;
}
void build_table(Table &L, int n){
L.size = n;
L.num = new int[n+4];
for(int i = 1; i <= n; i++){
scanf("%d", &L.num[i]);
}
}
int max_sum(Table L, int l, int r){
cnt++;
int sum1, sum2, sum3, sum4, mav3, mav4;
if(l == r){
if(L.num[l] < 0)
return 0;
else
return L.num[l];
}
int mid = (l+r)>>1;
sum1 = max_sum(L, l, mid);
sum2 = max_sum(L, mid+1, r);
sum3 = sum4 = 0, mav3 = mav4 = 0;
for(int i = mid; i >= l; i--){
sum3 += L.num[i];
mav3 = max(mav3, sum3);
}
for(int i = mid+1; i <= r; i++){
sum4 += L.num[i];
mav4 = max(mav4, sum4);
}
int ans = 0;
ans = max(sum1, sum2);
ans = max(ans, mav3+mav4);
return ans;
}
void delete_table(Table &L){
delete []L.num;
}
/*************************************************** User name: Result: Accepted Take time: 12ms Take Memory: 308KB Submit time: 2017-09-20 20:12:31 ****************************************************/
顺序表应用8:最大子段和之动态规划法
Time Limit: 5MS Memory Limit: 500KB
Problem Description
给定n(1<=n<=100000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。 例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
注意:本题目要求用动态规划法求解,只需要输出最大子段和的值。
Input
第一行输入整数n(1<=n<=100000),表示整数序列中的数据元素个数;
第二行依次输入n个整数,对应顺序表中存放的每个数据元素值。
Output
输出所求的最大子段和
Example Input
6
-2 11 -4 13 -5 -2
Example Output
20
Hint
Author
以下为Accepted代码
#include
#include
#include
using namespace std;
struct Table{
int size;
int *num;
};
void build_table(Table &L, int n);/*建表*/
int max_sum(Table L);/*动态规划法求最大子段和*/
void delete_table(Table &L);/*释放内存*/
int main(){
int n;
Table test;
while(~scanf("%d", &n)){
build_table(test, n);
printf("%d\n", max_sum(test));
delete_table(test);
}
return 0;
}
void build_table(Table &L, int n){
L.size = n;
L.num = new int[n+4];
for(int i = 1; i <= n; i++)
scanf("%d", &L.num[i]);
}
int max_sum(Table L){
int sum = 0, ans = 0;
for(int i = 1; i <= L.size; i++){
sum += L.num[i];/*以L.num[i]作为最后一位的子段和*/
if(sum < 0)
sum = 0;
ans = max(ans, sum);
}
return ans;
}
void delete_table(Table &L){
delete L.num;
}
/*************************************************** User name: Result: Accepted Take time: 8ms Take Memory: 308KB Submit time: 2017-09-20 20:31:41 ****************************************************/