PTA7-1 线性表合并
求解一般集合的并集问题。
已知两个集合A和B,现要求一个新的集合A=AUB。例如,设
A=(7,5,3,11)
B=(2,6,3)
合并后 A=(7,5,3,11,2,6)
输入格式:
第一行输入集合A的元素个数,第二行输入集合A的各元素值。
第三行输入集合B的元素个数,第四行输入集合B的各元素值。
输出格式:
输出完成合并后的集合A。
输入样例:
在这里给出一组输入。例如:
4
7 5 3 11
3
2 6 3
输出样例:
在这里给出相应的输出。例如:
7 5 3 11 2 6
解题思路
首先看到题目的基本思路用俩个数组代表集合一个数组代表合并后的数组,然后将这俩个数组合并并且把第二个数组中的和第一个数组有重复元素的数删除。这里我先用俩层for循环判断b数组中哪个数和a数组相同,如果相同就赋值一个比较大的数组(这里我选择99999),然后把a、b数组全部放入c数组,输出c数组时如果其值不为99999则输出即可。时间复杂度为O(n*m)。
代码实现
#include <iostream>
const int N = 10010;
using namespace std;
long long a[N], b[N], c[N];
int main()
{
int aa, bb;
cin >> aa; for (int i = 0; i < aa; i++) cin >> a[i];
cin >> bb; for (int i = 0; i < bb; i++) cin >> b[i];
int k = 0;//记录多少个重复的数
for (int i = 0; i < aa; i++)
for (int j = 0; j < bb; j++)
if (a[i] == b[j]) { b[j] = 99999; k++; }//去重操作
for (int i = 0; i < aa + bb; i++)
{
if (i < aa) c[i] = a[i];
else c[i]=b[i-aa];
// if (i >= aa) {
// if (b[i - aa] != 99999)c[i] = b[i - aa];
// else c[i] = -1;
// }
}
for (int i = 0; i < aa + bb; i++)
{
if (c[i] != 99999) cout << c[i] << " ";
}
}
PTA7-2 约瑟夫环
题目
N个人围成一圈顺序编号,从1号开始按1、2、3......顺序报数,报p者退出圈外,其余的人再从1、2、3开始报数,报p的人再退出圈外,以此类推。请按退出顺序输出每个退出人的原序号。
输入格式:输入只有一行,包括一个整数N(1<=N<=3000)及一个整数p(1<=p<=5000)。
输出格式:按退出顺序输出每个退出人的原序号,数据间以一个空格分隔,但行尾无空格。
输入样例 : 7 3
输出样例:3 6 2 7 5 1 4
第一种方法 数组模拟
首先准备一个比较长的数组(长度大于3000),基本思路为用数组下标代表这个人的序号,其值为0的话则表示他继续游戏,为1 的话代表他出局。然后将这个出局的人的数组下标依次按顺序放入另外一个等长的数组里面即可。
具体操作如下,用num记录有几个出局的人到n则退出循环,用k放入循环用来代表报数,如果k达到的m的值则令这个人出去并且k进行重置num++,代表重新开始循环报数
1#include <iostream>
#include <cstring>
#include <algorithm>
int a[10100],b[10010];//用一个比较长的数组 里面元素为0则未出局
using namespace std;
int main()
{
int n,m;cin>>n>>m;
int num=0,k=0,i=0,j=0; //num用于计数查看有多少个出局
// k用于记录报数出局之后 重置
while(num<n) {
i++;
if(i>n) i=1; // 相当于报数回到起点,走过了一轮
if(a[i]==0){
k++;
if(k==m){//代表这个人报数中奖 准备出局
a[i]=1;
k=0;num++;//重新开始报数,出局人数加1
b[j++]=i;
}
}
}
for(int t=0;b[t]!=0;t++)
{
if(t==0) cout<<b[t];
else cout<<" "<<b[t];
}
}
第二种循环链表
首先基本思路为创建一个循环链表,填数进去,然后进行循环遍历放入for循环进去当循环体到k时,用r=p再输出p->data,然后将r->next=p->next就相当于将p这个节点删除代表着p这个人出局
直到循环链表只剩下一个元素即p->next=p代表循环结束,最后把循环链表内的最后一个人输出即可。
#include <iostream>
#include <cstdlib>
#include<cstdio>
#include <algorithm>
using namespace std;
typedef struct node{
int data;
struct node *next;
}Node;
void ysfh(int n,int k){
Node *head=NULL,*p=NULL,*r=NULL;
head=(Node *)malloc(sizeof(Node));
if(head==NULL){
cout << " 内存请求失败" ;
return;
}
head->data=0;
head->next=NULL;
p=head;//头节点
for(int i=1;i<n;i++)
{
r=(Node *)malloc(sizeof(Node));
r->data=i;
r->next=NULL;
p->next=r;
p=r;
}
while(p->next!=p){//如果代表循环链表中只剩下一个元素
for(int i=1;i<k;i++)
{
r=p;
p=p->next; //这代表这个循环结束时 下一个p为出局的人
}
cout<<p->data<<" ";
r->next=p->next;//删除这个出局的
p=p->next;
}
cout<<p->data;//输出最后一个人
}
int main()
{
int n,k; cin>>n>>k;
ysfh(n,k);
return 0;
}
第三钟递归
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int ysf(int n,int k,int i){
if(i==1) return (n+k-1)%n;
else return (ysf(n-1,k,i-1)+k)%n;
}
int main()
{
int n,k;
cin>>n>>k;
for (int i = 1; i <= n; i ++ )
if(i==1)cout<<ysf(n,k,i)+1;
else cout << " " << ysf(n,k,i)+1;
}
PTA 7-3 俩个有序序列的中位数
已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数。有序序列A0,A1,⋯,AN−1的中位数指A(N−1)/2的值,即第⌊(N+1)/2⌋个数(A0为第1个数)。
输入格式:
输入分三行。第一行给出序列的公共长度N(0<N≤100000),随后每行输入一个序列的信息,即N个非降序排列的整数。数字用空格间隔。
输出格式:
在一行中输出两个输入序列的并集序列的中位数。
输入样例1:
5
1 3 5 7 9
2 3 4 5 6
输出样例1:
4
输入样例2:
6
-100 -10 1 1 1 1
-50 0 2 3 4 5
输出样例2:
1
解题思路
看到题目不经意联想起7-1的那个合并集合的,所以一开始用相同操作进行合并去重再排序之后交一发之后发现最后一个数据过不了,显示答案错误。然后开始看题,尝试了直接合并排序之后输出中位数,通过了。
代码实现
#include <iostream>
#include <cstring>
#include <algorithm>
const int N = 100010;
using namespace std;
int a[N],b[N],c[N];
int main()
{
int n; cin>>n;
for (int i = 0; i < n; i ++ ) cin>>c[i];
for (int i = 0; i < n; i ++ ) cin>>c[i+n];
sort(c,c+2*n);
cout<<c[(2*n-1)/2];
}