📂刷题
🔖PAT
2022-06-12 20:22阅读: 21评论: 0推荐: 0

PAT甲级刷题日记(二)

1020 Tree Traversals

Thu Jun 9 18:19
Link
25分
这题做复杂了,因为我建树了…后来看了柳神的题解发现不用建树就可以做。做法是先通过“已知后序中序求前序”的方法得到前序序列,但是每个节点都需要加一个index(是层次序列的编号,求法和手动用数组建二叉堆很相像,左孩子=父亲*2,右孩子=父亲*2+1,这里根节点下标是从1开始的),根据index对前序序列排序就可以得到层次遍历的序列。

已知后序与中序输出前序

摘录自柳神的博客

后序:3, 4, 2, 6, 5, 1(左右根)
中序:3, 2, 4, 1, 6, 5(左根右)
分析:因为后序的最后一个总是根结点,令i在中序中找到该根结点,则i把中序分为两部分,左边是左子树,右边是右子树。因为是输出先序(根左右),所以先打印出当前根结点,然后打印左子树,再打印右子树。左子树在后序中的根结点为root – (end – i + 1),即为当前根结点-(右子树的个数+1)。左子树在中序中的起始点start为start,末尾end点为i – 1.右子树的根结点为当前根结点的前一个结点root – 1,右子树的起始点start为i+1,末尾end点为end。
输出的前序应该为:1, 2, 3, 4, 5, 6(根左右)

void pre(int root, int start, int end) {
if(start > end) return ;
int i = start;
while(i < end && in[i] != post[root]) i++;
printf("%d ", post[root]);
pre(root - 1 - end + i, start, i - 1);
pre(root - 1, i + 1, end);
}

建树版AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
#define N 35
int n;
int post[N],in[N],lch[N],rch[N];
int level(int s1,int s2,int len){ // s1->in,s2->post
if(s1>=n||s2>=n||len<0||len>n) return -1;
int root=post[s2+len-1];
int pos=find(in,in+n,root)-in;
if(pos==n||pos<s1||pos>=s1+len) return -1;
lch[root]=level(s1,s2,pos-s1);
rch[root]=level(pos+1,s2+pos-s1,s1+len-pos-1);
return root;
}
void BFS(int root){
queue<int>q;
printf("%d",root);
if(lch[root]!=-1) q.push(lch[root]);
if(rch[root]!=-1) q.push(rch[root]);
while(!q.empty()){
root=q.front();
q.pop();
if(lch[root]!=-1) q.push(lch[root]);
if(rch[root]!=-1) q.push(rch[root]);
printf(" %d",root);
}
printf("\n");
}
int main() {
scanf("%d",&n);
for(int i=0;i<n;++i)
scanf("%d",&post[i]);
for(int i=0;i<n;++i)
scanf("%d",&in[i]);
int root=level(0,0,n);
BFS(root);
return 0;
}

1021 Deepest Root

Thu Jun 9 20:17
Link
25分
思路是:先用并查集判断图是否是连通的,如果连通就先随便找个点(我选定了点1),从这个点开始DFS一次,计算出另外n-1个点到点1的距离(即经过多少条边才能到达),然后找出距离的最大值以及距离点1最大的那个点的编号(可能不止一个,但是没关系,这里先找出一个),这时的最大值记为maxv。设这个点为x,那么这个x就一定是最长路径(可能不止一条)中的一个端点。然后从x开始再进行一次DFS,求出另外n-1个点到点x的距离,再找出最大值,这时的最大值就是最长路径的长度了,记为maxLen。然后,从1循环到n(保证答案从小到大输出),如果某个点满足它到1的距离等于maxv或者到x的距离等于maxLen,那么它就是最长路径的一个端点,直接输出即可。
注意n=1的情况,我是特判了的。
AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
#define N 10010
int n,maxLen;
int father[N],len[N];
vector<int>g[N];
bool vis[N];
int find_set(int x){
while(x!=father[x]){x=father[x]=father[father[x]];}
return x;
}
void DFS(int cur,int s,int arr[]){
vis[cur]=true;
arr[cur]=arr[s]+1;
for(int i=0;i<g[cur].size();++i)
if(!vis[g[cur][i]])
DFS(g[cur][i],cur,arr);
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;++i)
father[i]=i;
for(int i=1;i<=n-1;++i){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
int fu=find_set(u),fv=find_set(v);
if(fu!=fv) father[fu]=fv;
}
int cnt=0;
for(int i=1;i<=n;++i)
if(father[i]==i)
cnt++;
if(cnt>1){
printf("Error: %d components\n",cnt);
return 0;
}
if(n==1){
printf("1\n");
return 0;
}
memset(father,-1,sizeof(father));
DFS(1,1,father);
int maxv=0,cur=1;
for(int i=2;i<=n;++i)
if(father[i]>maxv){
maxv=father[i];
cur=i;
}
memset(vis,false,sizeof(vis));
memset(len,-1,sizeof(len));
DFS(cur,cur,len);
for(int i=1;i<=n;++i)
maxLen=max(maxLen,len[i]);
for(int i=1;i<=n;++i)
if(father[i]==maxv||len[i]==maxLen)
printf("%d\n",i);
return 0;
}

1023 Have Fun with Numbers

Thu Jun 9 21:22
Link
20分
AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
char s[25];
int num[25];
int v[10];
int main() {
scanf("%s",s);
int j=0;
for(int i=strlen(s)-1;i>=0;--i){
num[++j]=(int)(s[i]-'0');
v[num[j]]++;
num[j]<<=1;
}
for(int i=1;i<=j;++i){
num[i]+=num[i-1]/10;
num[i-1]%=10;
if(i-1>=1) v[num[i-1]]--;
}
v[num[j]%10]--;
if(num[j]>=10){
num[j+1]=num[j]/10;
num[j]%=10;
j++;
}
bool flag=true;
if(j>strlen(s)) flag=false;
else{
for(int i=0;i<=9;++i)
if(v[i]!=0){
flag=false;
break;
}
}
printf("%s\n",flag?"Yes":"No");
for(int i=j;i>=1;--i)
printf("%d",num[i]);
printf("\n");
return 0;
}

1024 Palindromic Number

Fri Jun 10 21:17
Link
25分
原来输入的数是低位在前、高位在后的,为了方便进位,需要将它倒过来,于是我用int数组倒序存储,后来看了柳神的题解发现其实还有更简单的方法,那就是用string读入后直接reverse(s.begin(), s.end()),在进行相加操作时也可以直接对字符进行相加,毕竟都是ASCII码嘛。判断是否需要进位,就直接判断s[i]>'9'即可。而且用string存储还有个好处,那就是判断是否是回文串时,可以直接判断s==t,其中字符串t是字符串s的reverse。
最后需要注意,如果给定的n就是一个回文数,那么一次相加操作都没有。我这里也写复杂了,其实直接从0遍历到k就行了。而且最后如果没有break(也就是在k步里没有得到回文数),那么此时应该输出k而不是i(我的代码里i在for外面定义的,因此跳出for时等于k+1)。总之,可以写成下面的简单形式:

cin >> s >> cnt;
for(i = 0; i <= cnt; i++) {
string t = s;
reverse(t.begin(), t.end());
if(s == t || i == cnt) break;
add(t);
}

add函数:

void add(string t) {
int len = s.length(), carry = 0;
for(int i = 0; i < len; i++) {
s[i] = s[i] + t[i] + carry - '0';
carry = 0;
if(s[i] > '9') {
s[i] = s[i] - 10;
carry = 1;
}
}
if(carry) s += '1';
reverse(s.begin(), s.end());
}

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
char s[15];
int num[200],tmp[200];
int k,n;
inline bool isPalindrome(){
for(int i=1;i<=(n>>1);++i)
if(num[i]!=num[1+n-i])
return false;
return true;
}
int main() {
scanf("%s%d",s,&k);
int i;
for(i=strlen(s)-1;i>=0;--i)
num[++n]=s[i]-'0';
if(isPalindrome()){
printf("%s\n0\n",s);
return 0;
}
for(i=1;i<=k;++i){
for(int i=1;i<=n;++i)
tmp[i]=num[i]+num[n+1-i];
for(int i=1;i<=n;++i)
num[i]=tmp[i];
for(int i=0;i<n;++i){
num[i+1]+=num[i]/10;
num[i]%=10;
}
if(num[n]>=10){
num[n+1]+=num[n]/10;
num[n]%=10;
n++;
}
if(isPalindrome()) break;
}
for(int j=n;j>=1;--j)
printf("%d",num[i]);
printf("\n%d\n",min(i,k));
return 0;
}

1027 Colors in Mars

Sat Jun 11 17:16
Link
20分
简单题,无坑。但还是没有一次AC qwq
AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
int r,g,b;
char a[15]="0123456789ABC";
int main() {
scanf("%d%d%d",&r,&g,&b);
printf("#%c%c%c%c%c%c\n",a[r/13],a[r%13],a[g/13],a[g%13],a[b/13],a[b%13]);
return 0;
}

1029 Median

Sun Jun 12 20:20
Link
25分
AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
int n1,n2,i,j,cnt,ans;
int a[200010],b[200010];
int main() {
scanf("%d",&n1);
for(i=1;i<=n1;++i)
scanf("%d",&a[i]);
scanf("%d",&n2);
for(j=1;j<=n2;++j)
scanf("%d",&b[j]);
int mid=(n1+n2+1)>>1;
i=1,j=1;
while(i<=n1&&j<=n2){
ans=a[i]<=b[j]?a[i++]:b[j++];
if(++cnt==mid) break;
}
if(cnt<mid&&i<=n1)
ans=a[i-1+mid-cnt];
else if(cnt<mid&&j<=n2)
ans=b[j-1+mid-cnt];
printf("%d\n",ans);
return 0;
}

本文作者:Ryomk

本文链接:https://www.cnblogs.com/preccrep/p/16360710.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Ryomk  阅读(21)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.

作曲 : Reol

作词 : Reol

fade away...do over again...

fade away...do over again...

歌い始めの一文字目 いつも迷ってる

歌い始めの一文字目 いつも迷ってる

どうせとりとめのないことだけど

伝わらなきゃもっと意味がない

どうしたってこんなに複雑なのに

どうしたってこんなに複雑なのに

噛み砕いてやらなきゃ伝わらない

ほら結局歌詞なんかどうだっていい

僕の音楽なんかこの世になくたっていいんだよ

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.

目の前 広がる現実世界がまた歪んだ

目の前 広がる現実世界がまた歪んだ

何度リセットしても

僕は僕以外の誰かには生まれ変われない

「そんなの知ってるよ」

気になるあの子の噂話も

シニカル標的は次の速報

麻痺しちゃってるこっからエスケープ

麻痺しちゃってるこっからエスケープ

遠く遠くまで行けるよ

安定なんてない 不安定な世界

安定なんてない 不安定な世界

安定なんてない きっと明日には忘れるよ

fade away...do over again...

fade away...do over again...

そうだ世界はどこかがいつも嘘くさい

そうだ世界はどこかがいつも嘘くさい

綺麗事だけじゃ大事な人たちすら守れない

くだらない 僕らみんなどこか狂ってるみたい

本当のことなんか全部神様も知らない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.

点击右上角即可分享
微信分享提示