数组归并
总时间限制: 3000ms 内存限制: 65535kB
描述
有两个数组A={a1,a2,…,an}, B={b1,b2,…,bm}。
其中a1<=a2<=…<=an, b1<=b2<=…<=bm, 要求将其合并为一个更大的有序数组,并且去除重复元素。
输入
第一行输入一个整数t,表示测试数据的组数。
对于每组测试数据,第一行输入两个整数n、m。分别代表数组A和B的长度。第二行输入n个整数,代表A的各个元素。第三行输入m个整数,代表B的各个元素。
1<=n,m<=100000.
输出
对于每组数据,输出两行。第一行输出一个整数K,表示合并后数组的元素个数。第二行输出K个整数,代表合并后数组的各个元素。
样例输入
4
//我自己加的空行
3 3
1 3 5
2 3 4
2 2
1 2
3 4
2 3
11 12
1 2 3
3 3
1 1 1
2 2 3
样例输出
5
1 2 3 4 5
4
1 2 3 4
5
1 2 3 11 12
3
1 2 3
提示
利用AB两个数组已经有序的条件,考虑元素重复.
n,m较大,数组应该开成全局变量
代码
#include <stdio.h>
#include <string.h>
#include <math.h>
int a[100001] = {}, b[100001] = {}, c[200001];
int min(int x, int y)
{
if (x > y)return y;
else return x;
}
int merge(int n, int m)
{
int i = 0, j = 0, t = 0, e = min(a[0],b[0])-1;//错误3:之前令e=0,但是题目中录入的是【整数】,所以有可能会录入0或者负数(虽说测试点中并没有出现负数x)
while (i < n || j < m)
{
int x = a[i], y = b[j];
if (i == n)//a已经遍历完了之后,只看b了
{
for (int l = j; l < m; l++)
{
if (b[l] > e)//(之前犯的)错误1:并不是说a录完了之后就把所有的剩下的b都录进来orz
{
c[t] = b[l];
e = b[l];
t++;
}
}
break;//把b也录完了,就直接退出(其实也没必要退出,现在i=n,j=m自然会退出循环了)
}
if (j == m)
{
for (int l = i; l < n; l++)
{
if (a[l] > e)
{
c[t] = a[l];
e = a[l];
t++;
}
}
break;
}
if (x == y)
{
if (e == x)
{
i++, j++;
}
else if (e < x)
{
c[t] = x;
e = x;
i++, j++, t++;
}
}
if (x > y)
{
if (e == y)
{
j++;
}
if (e < y)//e<y<x
{
c[t] = y;
e = y;
t++, j++;
}
}
if (y > x)
{
if (e == x)
{
i++;
}
if (e < x)//错误2:并不是说e<x<y就得(在这一次)把y也给录进去,有可能下一个x还比y小
{
c[t] = x;
e = x;
t++, i++;
}
}
}
printf("%d\n",t);
for (int i = 0; i < t; i++)
{
printf("%d ", c[i]);
}
printf("\n");
return 0;
}
int main()
{
int T;
scanf("%d", &T);
for (int i = 1; i <= T; i++)
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
for (int i = 0; i < m; i++)
{
scanf("%d", &b[i]);
}
merge(n, m);
}
}
这道题和那个双指针的练习差不多,不过有更多细碎的东西,题目不难,但是感觉很多小地方很需要耐心处理…
而且感觉有更简洁的方法emm