pat甲级题库

pat甲级题库

1020 Tree Traversals

  1. Traversalsn. /trəˈvərs(ə)l/ [计] 遍历;横越;横断物
  2. distinct /dɪˈstɪŋkt/ adj. 明显的;独特的
  3. sequences 美 /ˈsiːkwənsɪz/ n. 数 序列,顺序;
image 20200827195828492

Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and inorder traversal sequences, you are supposed to output the level order traversal sequence of the corresponding binary tree.

假设二叉树中的所有键都是不同的正整数。给定了postorder和inorder遍历序列,您应该输出相应二叉树的level order遍历序列。

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the postorder sequence and the third line gives the inorder sequence. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the level order traversal sequence of the corresponding binary tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

Sample Output:

4 1 6 3 5 7 2

题解:

//
// Created by jiayadong on 2020/8/27.
//
/**
 *后序+前序=
 */

#include <iostream>
#include <queue>
using  namespace std;

const int maxn=50;

struct node{
    int data;
    node* lchild;
    node* rchild;
};

//设置全局变量,先序数组,中序数组,后序数组
int pre[maxn],in[maxn],post[maxn];
int n;  //结点个数

//当前二叉树的后序序列区间为[posL,posR],中序序列区间为[intL ,inR];
/**
 *
 * @param posL 后序左
 * @param postR 后序右
 * @param inL 中序左
 * @param inR 中序右
 * @return
 */
node *create(int postL,int postR, int inL,int inR)
{
//    递归边界
    if (postL>postR){
        return NULL;
    }
//    申请一个根节点,用来存放
    node* root=new node;
    root->data=post[postR];
//    开始寻找左右子树个数
    int k;
    for (k = inL; k <=inR ; k++) {
        if (in[k]==post[postR]){
            break;
        }
    }

//    中序序列找出左右子树个数
    int numLeft=k-inL;
    root->lchild = create(postL,postL+numLeft-1,inL,k-1);
    root->rchild = create(postL+numLeft,postR-1,k+1,inR);
//    返回根节点
    return root;
}

//已经输出根节点个数
    int num= 0;
//    层序遍历
void BFS(node* root)
{
    queue<node*> q;  //这里队列放的是地址
    q.push(root);
    while (!q.empty()){
        node *now=q.front();
        q.pop();
        num++;
        cout<<now->data;
        if (num<n) cout<<" ";
        if (now->lchild!=NULL) q.push(now->lchild);
        if (now->rchild!=NULL) q.push(now->rchild);

    }


}

int main(){
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>post[i];

    }
    for(int i=0;i<n;i++)
    {
        cin>>in[i];
    }
    node *root=create(0,n-1,0,n-1);
//    建树
    BFS(root);

    return 0;
}

1053 Path of Equal Weight (30分)

Given a non-empty tree with root R, and with weight W**i assigned to each tree node T**i. The weight of a path from *R* to *L* is defined to be the sum of the weights of all the nodes along the path from R to any leaf node L.

Now given any weighted tree, you are supposed to find all the paths with their weights equal to a given number. For example, let’s consider the tree showed in the following figure: for each node, the upper number is the node ID which is a two-digit number, and the lower number is the weight of that node. Suppose that the given number is 24, then there exists 4 different paths which have the same given weight: {10 5 2 7}, {10 4 10}, {10 3 3 6 2} and {10 3 3 6 2}, which correspond to the red edges in the figure.

dopxET.jpg

Input Specification:

Each input file contains one test case. Each case starts with a line containing 0<N≤100, the number of nodes in a tree, M (<N), the number of non-leaf nodes, and 0<S<230, the given weight number. The next line contains N positive numbers where W**i (<1000) corresponds to the tree node T**i. Then M lines follow, each in the format:

ID K ID[1] ID[2] ... ID[K]

where ID is a two-digit number representing a given non-leaf node, K is the number of its children, followed by a sequence of two-digit ID's of its children. For the sake of simplicity, let us fix the root ID to be 00.

Output Specification:

For each test case, print all the paths with weight S in non-increasing order. Each path occupies a line with printed weights from the root to the leaf in order. All the numbers must be separated by a space with no extra space at the end of the line.

Note: sequence {A1,A2,⋯,A**n} is said to be greater than sequence {B1,B2,⋯,B**m} if there exists 1≤k<min{n,m} such that A**i=B**i for i=1,⋯,k, and A**k+1>B**k+1.

Sample Input:

20 9 24
//结点树 非叶子结点 常数S
10 2 4 3 5 10 2 18 9 7 2 2 1 3 12 1 8 6 2 2
00 4 01 02 03 04
02 1 05
04 2 06 07
03 3 11 12 13
06 1 09
07 2 08 10
16 1 15
13 3 14 16 17
17 2 18 19

Sample Output:

10 5 2 7
10 4 10
10 3 3 6 2
10 3 3 6 2

Special thanks to Zhang Yuan and Yang Han for their contribution to the judge’s data.

题解:

//
// Created by jiayadong on 2020/8/28.
//
/**
 * 注意点:<br>
 * <li>1.有多条路径时,有更高全值的路径应该先输出.由于在读入时已经对每个节点所有子节点按权值从大到小排序
 * <li>所以在递归过程中总是会先访问所有子节点中权值更大的
 * <li>2.
 *
 */

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=100010;
struct node{
    int weight;  //权重
    vector<int> child;  //指针域

}Node[maxn];
//要有一个比较函数
bool cmp(int a,int b)
{
//    按结点数据域从大到小排序
    return Node[a].weight>Node[b].weight;
}

/**
 * 一些全局变量
 *
 */
//结点,边数,给定的和
int n,m,s;
int path[maxn];   //记录路径

/**
 *
 * @param index        当前访问结点为index
 * @param numNode      numNode为当前路径path上的结点个数
 * @param sum          sum
 */
void DFS(int index, int numNode,int sum)
{
    if (sum>s) return;
    if (sum==s) {
        if (Node[index].child.size()!=0) return;
//        满足条件
        for(int i=0;i<numNode;i++)
        {
            cout<<Node[path[i]].weight;
            if (i<numNode-1) cout<<" ";
            else cout<<endl;

        }
        return;

    }

//    枚举所有子节点
    for(int i=0;i<Node[index].child.size();i++)
    {
        int child=Node[index].child[i];
        path[numNode]=child;
//        遍历孩子结点,将层数加一
        DFS(child,numNode + 1,sum + Node[child].weight);
    }

}

 int main(){
      cin>>n>>m>>s;
      for(int i=0;i<n;i++)
      {
          cin>>Node[i].weight;

      }
//   id为结点,  k为孩子个数
      int id,k,child;

      for(int i=0;i<m;i++)
      {
          cin>>id>>k;
          for(int j=0;j<k;j++)
          {
//              child为结点为id的孩子
              cin>>child;
              Node[id].child.push_back(child);

          }
//          接收了一个结点的孩子,再让这个整个孩子进行排序
        sort(Node[id].child.begin(),Node[id].child.end(),cmp);   //排序
      }
      path[0]=0;  //路径第一个结点设置为0号结点
//      此时的结点个数是第一个结点,而且结点个数为1,为0号结点个数
      DFS(0,1,Node[0].weight);  //DFS求解
     return 0;
 }

1043 Is It a Binary Search Tree (25分)

recursively 英 /ri’kəsivli/ adv. 递归地;递回地

Mirror Image 镜像

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node’s key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
  • Both the left and right subtrees must also be binary search trees.

If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.

Now given a sequence of integer keys, you are supposed to tell if it is the preorder traversal sequence of a BST or the mirror image of a BST.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤1000). Then N integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, first print in a line YES if the sequence is the preorder traversal sequence of a BST or the mirror image of a BST, or NO if not. Then if the answer is YES, print in the next line the postorder traversal sequence of that tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.

Sample Input 1:

7
8 6 5 7 10 8 11

Sample Output 1:

YES
5 7 6 8 11 10 8

Sample Input 2:

7
8 10 11 8 6 7 5

Sample Output 2:

YES
11 8 10 7 5 6 8

Sample Input 3:

7
8 6 8 5 10 9 11

Sample Output 3:

NO

判断给出的序列是不是二叉排序树的先序序列或者是镜像二叉排序树的先序序列

二叉树的遍历主要有三种:

(1)先(根)序遍历(根左右)

(2)中(根)序遍历(左根右)

(3)后(根)序遍历(左右根)
image 20200829123702845

djiuHU.png

1034 Head of a Gang (30分)

guaranteed n. 保证;担保;保证人;保证书;抵押品

alphabetical adj. 字母的;[计] 依字母顺序的

cluster

One way that the police finds the head of a gang is to check people’s phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls made between the two persons. A “Gang” is a cluster of more than 2 persons who are related to each other with total relation weight being greater than a given threshold K. In each gang, the one with maximum total weight is the head. Now given a list of phone calls, you are supposed to find the gangs and the heads.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive numbers N and K (both less than or equal to 1000), the number of phone calls and the weight threthold, respectively. Then N lines follow, each in the following format:

Name1 Name2 Time

where Name1 and Name2 are the names of people at the two ends of the call, and Time is the length of the call. A name is a string of three capital letters chosen from A-Z. A time length is a positive integer which is no more than 1000 minutes.

Output Specification:

For each test case, first print in a line the total number of gangs. Then for each gang, print in a line the name of the head and the total number of the members. It is guaranteed that the head is unique for each gang. The output must be sorted according to the alphabetical order of the names of the heads.

Sample Input 1:

8 59
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10

Sample Output 1:

2
AAA 3
GGG 3

Sample Input 2:

8 70
AAA BBB 10
BBB AAA 20
AAA CCC 40
DDD EEE 5
EEE DDD 70
FFF GGG 30
GGG HHH 20
HHH FFF 10

Sample Output 2:

0

思路

  1. 步骤一:要解决姓名和编号的对应关系,
    1. 一种是使用map<string,int> 直接建立字符串与整型的映射关系
    2. 是使用hash的方法将字符串转换为整型,编号与姓名的对应关系则可以直接用string数组进行定义,使用map<int,string> 也行
  2. 步骤二:进行每条边的权值,能够在读入的时候递增点权值,根据需要获取每个人的点权,事实上这一步是为了求与某个点相连的边的边权之和
  3. 进行图的遍历.使用DFS遍历每个联通块,目的是获取每个连通快的头目(即连通块内点权最大的节点),成员个数,总边权
  4. 通过步骤三可以求出连通快总边权totalValue.如果totalValue大于给定的阈值k,而且成员人数大于2,则说明该连通图是一个团伙,将该团伙的信息存储下来

注:可以定义map<string,int> 来建立团伙头目和姓名和团伙成员人数的映射关系.由于map中元素自动按键值从小到大排序,可以自动满足题目了题目要求的"姓名字典从小到大输出"的规定

本题可以使用并查集解决,在使用并查集时,要注意合并函数中需要总是保持点权更大的结点为集合的根结点
我们还需要设置两个数组
1.用来存放以当前结点为根结点的集合的总边权
2.另一个数组用来存放以当前结点为根结点的集合的成员人数

这一套函数下来简直像艺术品一样

//
// Created by jiayadong on 2020/8/30.
//

/**
 * 这个题是关于什么的?
 * 每一个连通分量的路径长度大于K
 * 并且找出他们的头目以及成员个数
 * 即起点个数和总结点个数
 */
#include <iostream>
#include <string>
#include <map>
#include <cstring>
using namespace std;

const int maxn=2010;        //总人数
const int INF=1000000000;   //无穷大

/**
 *
 */
map<int ,string> intToString;    //编号->姓名
map<string , int> stringToInt;   //姓名->编号
map<string , int> Gang;          // head->人数

//邻接矩阵G,点权值为weight
int G[maxn][maxn] = {0} , weight[maxn] = {0};

//边数n,下限k,总人数numPerson
int n, k , numPerson = 0;

//标记是否被访问
bool vis[maxn] ={false};

/**
 *
 * @param nowVisit      当前访问的编号
 * @param head          头目
 * @param numMember     成员编号
 * @param totalValue    连通快的总边权
 */
void DFS(int nowVisit, int& head,int& numMember, int& totalValue)
{
//    一个连通遍历里的人数
    numMember++;

    vis[nowVisit] = true;

    if(weight[nowVisit] > weight[head])
    {
        head=nowVisit;
    }
//    枚举所有人
    for(int i=0;i<numPerson;i++)
    {
//        如果从nowVisit能到达i
        if (G[nowVisit][i] > 0){

            totalValue += G[nowVisit][i] ;
//            删除这条边,防止
            G[nowVisit][i] =G[i][nowVisit] =0;

            if ( vis[i] == false ) {

                DFS(i,head,numMember , totalValue );

            }
        }

    }

}

/**
 * 函数遍历整个图,获取每个连通块的信息
 */
void DFSTrave()
{
    for(int i=0;i<numPerson;i++)
    {
        if (vis[i] == false) {
//            头目,成员数,总边权
            int head = i, numMember = 0,totalValue = 0;
//            遍历i所在的连通块

            DFS(i , head , numMember , totalValue);
//            如果成员数大于2且总边权大于k,head人数为numMember
            if (numMember >2 && totalValue > k) {

                Gang[ intToString[head]] = numMember;

            }
        }

    }

}

//
int change(string str)
{
    if (stringToInt.find(str) != stringToInt.end())
    {
        return stringToInt[str];
    } else{
//        str的编号为numPerson,numPerson对应str
        stringToInt[str] = numPerson;
        intToString[numPerson] = str;
        return numPerson++;
    }

}

int main(){
   int w;
   string str1 , str2;
   cin>>n>>k;

   for(int i=0;i < n;i++)
   {
       cin >>str1 >>str2 >>w;

       int id1 = change(str1);
       int id2 = change(str2);

       weight[id1] += w;
       weight[id2] += w;

       G[id1][id2] +=w;  //边id1->id2的边权增加w
       G[id2][id1] +=w;   //边id2->id1的边权增加w

   }

    DFSTrave(); //遍历整个图的所有连通块,获取Gang的信息
    cout <<Gang.size() <<endl;


    for (auto it = Gang.begin();  it!=Gang.end() ; it++) {
        cout<<it->first <<" "<<it->second <<endl;
    }


    return 0;
}

1076 Forwards on Weibo (30分)

Forwards

potential adj. 潜在的,可能的;势的

specific user adj:特殊的用户

Hence adv. 因此;今后

guaranteed v. 保证;提供(产品)保修单;

initial adj. 最初的;字首的

Weibo is known as the Chinese version of Twitter. One user on Weibo may have many followers, and may follow many other users as well. Hence a social network is formed with followers relations. When a user makes a post on Weibo, all his/her followers can view and forward his/her post, which can then be forwarded again by their followers. Now given a social network, you are supposed to calculate the maximum potential amount of forwards for any specific user, assuming that only L levels of indirect followers are counted.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers: N (≤1000), the number of users; and L (≤6), the number of levels of indirect followers that are counted. Hence it is assumed that all the users are numbered from 1 to N. Then N lines follow, each in the format:

M[i] user_list[i]

where M[i] (≤100) is the total number of people that user[i] follows; and user_list[i] is a list of the M[i] users that followed by user[i]. It is guaranteed that no one can follow oneself. All the numbers are separated by a space.

Then finally a positive K is given, followed by K UserID's for query.

翻译一下:
614/5000

每个输入文件包含一个测试用例。 对于每种情况,第一行包含2个正整数:N(≤1000),用户数; L(≤6),即被计数的间接关注者的级别数。 因此,假定所有用户的编号都从1到N。然后是N行,每行的格式为:
其中M [i](≤100)是用户[i]跟随的总人数; 和user_list [i]是M [i]个用户列表,后跟user [i]。 保证没有人可以跟随自己。 所有数字都用空格分隔。

然后,最后给出一个正数K,后跟K个用户ID进行查询。

Output Specification:

For each UserID, you are supposed to print in one line the maximum potential amount of forwards this user can trigger, assuming that everyone who can view the initial post will forward it once, and that only L levels of indirect followers are counted.

对于每个UserID,假设每个可以查看初始帖子的用户都将转发一次,并且只计算L级间接关注者,则应该在一行中打印出该用户可以触发的最大潜在转发量。

Sample Input:

7 3
3 2 3 4
0
2 5 6
2 3 1
2 3 4
1 4
1 5
2 2 6

Sample Output:

4
5
djiQN4.png dji3C9.png

在clion中处理的时候,出现了数据问题,DEV和oj上没有这种问题出现

//
// Created by jiayadong on 2020/8/31.
//
#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int maxn=2001;


struct Node{
    int v;          //结点编号
    int layer;      //结点层号
};

vector<Node> Adj[maxn];

bool vis[maxn] ={false};

/**
 *
 * @param s 结点编号
 * @param L 层数限制
 * @return
 */
int BFS(int s,int L)
{
    int numForward = 0;  //转发数
    queue<Node> q;
    Node start;
    start.v=s;
    start.layer=0;
    q.push(start);
    vis[start.v] = true;
    while (!q.empty())
    {
//        取出队首元素
        Node Top=q.front();
        q.pop();
        int u=Top.v;
        for(int i=0;i<Adj[u].size();i++)
        {
            Node next=Adj[u][i];
            
            next.layer = Top.layer+1;
            if (vis[next.v] == false && next.layer <= L){
                q.push(next);
                vis[next.v] = true;
                numForward++;     //转发数加1
            }

        }

    }

    return numForward;  //返回转发数数字

}

int main(){
    Node user;
    int n,L,numFollow,idFollow;
    cin>>n>>L;
    for(int i=1;i<=n;i++)
    {
        user.v=i;           //用户编号为i
        cin>> numFollow;
        for(int j =0;j<numFollow; j++)
        {
            cin>>idFollow;                  //i号用户关注的用户编号
            Adj[idFollow].push_back(user);  //边idFollow->i
            
        }

    }
    int numQuery, s;
    cin>>numQuery;
    for(int i=0;i<numQuery;i++)
    {
//        因为要使用两次,所以一些数组要进行初始化
        memset(vis, false , sizeof(vis));
        cin>>s;
        
        cout<< BFS(s,L)<<endl;

    }

    return 0;
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

以码平川

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值