中国大学MOOC-陈越、何钦铭-数据结构-起步能力自测题笔记
解题的方法有很多种,这些仅仅是我的解题方法,不是最优的,但是是我能最快想到的。
题集链接:https://pintia.cn/problem-sets/17/problems/type/7
自测1-打印沙漏
题意:给你n个字符,例如*,用这n个*字符组成这种类型的图案,输出能够组成的最大的图案和剩余的字符数量。
分析:只要计算出n个字符可以组成图案的最大规模以及剩余的字符数量。再按照要求输出该图案即可。
思路:根据计算可得出图案字符数量与规模的规律,分析每一行字符和空格与行数的关系。再把图案上半部分和最中间那部分设计输出,下半部分与上半部分对称,只需倒过来输出即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,sum=1,m=0,temp=1;
char x;
scanf("%d",&n);
getchar();
scanf("%c",&x);
if(n==1){
printf("%c\n",x);
printf("0\n");
}else{
while(n>sum){
m+=1;
temp=(temp+2);
sum+=temp*2;
}
temp-=2;
m-=1;
for(int i=0;i<m;i++){
for(int j=0;j<i;j++){
printf(" ");
}
for(int j=0;j<temp-i*2;j++){
printf("%c",x);
}
printf("\n");
}
for(int i=0;i<m;i++){
printf(" ");
}
printf("%c\n",x);
for(int i=m-1;i>=0;i--){
for(int j=0;j<i;j++){
printf(" ");
}
for(int j=0;j<temp-i*2;j++){
printf("%c",x);
}
printf("\n");
}
printf("%d\n",n-sum+(temp+2)*2);
}
return 0;
}
自测2-素数对猜想
题意:给出一个数n,找出1-n内的素数对个数,素数对要满足a,b都为素数,且a=b+2;
分析:找到1-n内的素数,在判断那些素数对满足a=b+2。
思路:循环跑一遍3-n内的奇数,偶数不可能是素数,2也不能和哪个素数满足a=b+2。判断该数和该数加二的数是否都为素数,都为素数即是一个素数对,统计素数对数量即可。
判断素数:如果该数x不能整除2到根号x中的任何一个数,那这个数即为素数。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,temp,sum=0;
scanf("%d",&n);
for(int i=3;i<=n-2;i+=2){
temp=0;
for(int j=2;j<=sqrt(i);j++){
if(i%j==0){
temp=1;
break;
}
}
if(temp==0){
//i+=2;
for(int j=2;j<=sqrt(i+2);j++){
if((i+2)%j==0){
temp=1;
break;
}
}
if(temp==0){
sum++;
// printf("%d %d\n",i,i+2);
}
}
}
printf("%d\n",sum);
return 0;
}
自测3-数组元素循环右移
题意:给出一组数和x,该组数每个位置上的数向右移x位,末位的数移到首位。输出移位后的数列。
分析:每个数的实际位置改变了,但他们的相对位置不变。只要找出第一个数移位后的位置,根据相对位置就可以判断出其他数的位置。
思路:位移位数取余数组长度为首位的移位后的位置,(数列长度为n移位n后位置不变),把数组中移位后的数移到最前(取余数组长度即可)。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int m,n,x[110];
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
scanf("%d",x+i);
}
n=n%m;
int temp=0;
for(int i=m-n;i<m;i++){
if(i!=m-n&&temp!=0){
printf(" ");
}
printf("%d",x[i]);
temp=1;
}
for(int i=0;i<m-n;i++){
if(temp!=0){
printf(" ");
}
printf("%d",x[i]);
temp=1;
}
return 0;
}
自测4-Have Fun with Numbers
题意:给出一个整数x,这个数乘2之后的数y。判断组成x每个位上的数与y每个位上数是否相同。如x=132,y=264。这两个不同,x由1,2,3组成,而y由2,4,6组成。
分析:给出的数很大,超出了数字类型的最大范围,首先想到大数运算,用字符串模拟数字运算。再记录x与y每个位上的数记录下来,最后对比即可。
思路:用字符串数组模拟整数,用一个数组储存0-9在x每个位上出现的次数。对每个位上的数乘二逢10进位表示y,用一个数组储存0-9在y每个位上出现的次数。最后比较两个数组是否相同。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
char x[31],y[31];
int a[20],b[20],num1[31],num2[31],temp=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
scanf("%s",x);
int len1=strlen(x),len2;
for(int i=0;i<len1;i++){
a[x[i]-'0']++;
num1[i]=x[i]-'0';
}
for(int i=len1-1;i>=0;i--){
int p=(num1[i]*2+temp);
num2[len1-1-i]=p%10;
b[p%10]++;
temp=p/10;
}
len2=len1;
if(temp!=0){
num2[len1]=temp;
len2+=1;
b[temp]++;
}
temp=0;
for(int i=0;i<10;i++){
if(a[i]!=b[i]){
temp=1;
break;
}
}
if(temp==0){
printf("Yes\n");
}else{
printf("No\n");
}
for(int i=len2-1;i>=0;i--){
printf("%d",num2[i]);
}
return 0;
}
自测五-Shuffling Machine
题意:模拟洗牌,给出牌的初始序列和洗牌规则,要求按照这个规则洗牌k次,输出牌经过k次洗牌后的序列。
洗牌规则:给出一组数列,数列长度和牌的长度一样,第i个数a[i]表示第i张牌洗到第a[i]个位置上。
分析:只要按照规则洗牌,记录每次洗牌后的牌的顺序,最后再输出牌的顺序即可。
思路:用两个数组,轮番记录每次洗牌前后的牌的顺序。洗牌k次后数次洗牌后的牌序列即可。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string x[60]={"S1","S2","S3","S4","S5","S6","S7","S8","S9","S10","S11","S12","S13"
,"H1","H2","H3","H4","H5","H6","H7","H8","H9","H10","H11","H12","H13"
,"C1","C2","C3","C4","C5","C6","C7","C8","C9","C10","C11","C12","C13"
,"D1","D2","D3","D4","D5","D6","D7","D8","D9","D10","D11","D12","D13"
,"J1","J2"},y[60],z[60];
int n,ord[60];
scanf("%d",&n);
for(int i=0;i<54;i++){
scanf("%d",ord+i);
// y[ord[i]]=x[i];
}
while(1){
for(int i=0;i<54;i++){
y[ord[i]-1]=x[i];
}
n-=1;
if(n==0){
for(int i=0;i<54;i++){
if(i!=0){
cout<<" ";
}
cout<<y[i];
}
break;
}
for(int i=0;i<54;i++){
x[ord[i]-1]=y[i];
}
n-=1;
if(n==0){
for(int i=0;i<54;i++){
if(i!=0){
cout<<" ";
}
cout<<x[i];
}
break;
}
}
return 0;
}
亲身下河知深浅,亲口尝梨知酸甜。