PAT甲级题目翻译+答案 AcWing(链表)

1032 Sharing (25 分)

题意 :

  • suffix后缀;prefix前缀
  • 每个结点存一个字母,一共存两个单词
  • 分别给两个单词的第一个字母的地址以及总共的结点数
  • 给出所有结点的地址数值和下一个结点的地址(null就是-1)
  • 要求这两个单词最长公共后缀的起始位置的结点的地址,没有就输出-1

思路 :

  • 讲了一堆,模拟样例一发现就是找到两个链表中第一个拥有相同地址的结点,并输出这个地址,如果没有这个结点,就输出-1
  • 只要把第一个链表中每个地址都标记,遍历第二个链表的时候如果当前这个结点的地址被标记过,就return
  • 结点值和结点的下一个结点的地址,可以分别用两个数组存储,因为这里的地址最多是5位数,可以充当数组下标;e数组表示地址对应的结点值;ne数组表示地址对应下一个结点的地址
  • 链表的表头地址很重要

语法 :

  • 5位地址,输出记得格式化
#include 
using namespace std;

const int N = 1e5 + 10;

int n;
int h1, h2, ne[N];
char e[N];
bool st[N];

int main()
{
    scanf("%d%d%d", &h1, &h2, &n);
    
    int address, next;
    char data;
    for (int i = 0; i < n; i ++ )
    {
        scanf("%d %c %d", &address, &data, &next);
        e[address] = data, ne[address] = next;
    }
    
    for (int i = h1; ~i; i = ne[i])
        st[i] = true;
    
    for (int i = h2; ~i; i = ne[i])
        if (st[i])
        {
            printf("%05d\n", i);
            return 0;
        }
    
    puts("-1");
}

1052 Linked List Sorting (25 分)

题意 :

  • 给一个链表,要求按照值排序后,输出链表

思路 :

  • 本题可能包含不在链表中的结点,这些结点无需统计(从它问你结点数推测),因此另外开一个vector重新建立链表
  • 链表可能为空
  • 且有可能同一个结点输入多次,所以用map存地址对应的结点更好
  • 以上这些题目都没有告诉你。。
  • 我们这里的地址用string而不用int,好处是就不需要格式化%05d了,它这样用到的地址全部是输入给你的地址,不会由于int和string的转换失去前导零

语法 :

  • for中可以string做循环变量,通过map重建vector版本链表
#include 
#include 
#include 
#include 
using namespace std;

struct Node
{
    string address;
    int key;
    string next;
    
    bool operator< (const Node& t) const
    {
        return key < t.key;
    }
};

int main()
{
    int n;
    char head[10];
    scanf("%d %s", &n, head);
    
    unordered_map<string, Node> map;
    
    char address[10], next[10];
    int key;
    while (n -- )
    {
        scanf("%s %d %s", address, &key, next);
        map[address] = {address, key, next};
    }
    
    vector<Node> nodes;
    for (string i = head; i != "-1"; i = map[i].next) nodes.push_back(map[i]);
    
    printf("%d ", (int)nodes.size());
    if (nodes.empty()) puts("-1");
    else
    {
        sort(nodes.begin(), nodes.end());
        
        printf("%s\n", nodes[0].address.c_str());
        for (int i = 0; i < nodes.size(); i ++ )
        {
            if (i + 1 == nodes.size())
                printf("%s %d -1", nodes[i].address.c_str(), nodes[i].key);
            else
                printf("%s %d %s\n", nodes[i].address.c_str(), nodes[i].key, nodes[i + 1].address.c_str());
        }
    }
}

1074 Reversing Linked List (25 分)

题意 :

  • 给一个链表和一个k,要求每k个结点为一组逆序,输出逆序后的链表

思路 :

  • 按逻辑顺序将链表的地址放入vector中
  • 注意输出链表的时候不是输出ne,而是输出q[i + 1]
#include 
#include 
#include 
using namespace std;

const int N = 1e5 + 10;

int n, head, m;
int e[N], ne[N];

int main()
{
    scanf("%d%d%d", &head, &n, &m);
    
    int address, data, next;
    for (int i = 0; i < n; i ++ )
    {
        scanf("%d%d%d", &address, &data, &next);
        e[address] = data, ne[address] = next;
    }
    
    vector<int> q;
    
    for (int i = head; ~i; i = ne[i]) q.push_back(i);
    
    for (int i = 0; i + m - 1 < q.size(); i += m )
    {
        reverse(q.begin() + i, q.begin() + i + m);
    }
    
    for (int i = 0; i < q.size(); i ++ )
    {
        printf("%05d %d ", q[i], e[q[i]]);
        if (i != q.size() - 1) printf("%05d\n", q[i + 1]);
        else printf("-1\n");
    }
}

1097 Deduplication on a Linked List (25 分)

题意 :

  • data deduplication 重复元素删除
#include 
#include 
#include 

using namespace std;

const int N = 100010;

int n;
int h, e[N], ne[N];
bool st[N];

int main()
{
    scanf("%d%d", &h, &n);
    for (int i = 0; i < n; i ++ )
    {
        int address, key, next;
        scanf("%d%d%d", &address, &key, &next);
        e[address] = key, ne[address] = next;
    }

    vector<int> a, b;
    for (int i = h; i != -1; i = ne[i])
    {
        int v = abs(e[i]);
        if (st[v]) b.push_back(i);
        else
        {
            st[v] = true;
            a.push_back(i);
        }
    }

    for (int i = 0; i < a.size(); i ++ )
    {
        printf("%05d %d ", a[i], e[a[i]]);
        if (i + 1 == a.size()) puts("-1");
        else printf("%05d\n", a[i + 1]);
    }
    for (int i = 0; i < b.size(); i ++ )
    {
        printf("%05d %d ", b[i], e[b[i]]);
        if (i + 1 == b.size()) puts("-1");
        else printf("%05d\n", b[i + 1]);
    }

    return 0;
}

1133 Splitting A Linked List (25 分)

题意 :

  • Splitting A Linked List 链表元素分类
  • 给定一个单链表,请编写程序将链表元素进行分类排列,使得所有负值元素都排在非负值元素的前面,而 [0,K] 区间内的元素都排在大于 K 的元素前面。
  • 但每一类内部元素的顺序是不能改变的。

语法 :

  • a.insert(a.end(), b.begin(), b.end());,在vector a容器的末尾加入vector b容器
#include 
#include 
#include 

using namespace std;

const int N = 100010;

int n, k;
int h, e[N], ne[N];

int main()
{
    scanf("%d%d%d", &h, &n, &k);
    for (int i = 0; i < n; i ++ )
    {
        int address, key, next;
        scanf("%d%d%d", &address, &key, &next);
        e[address] = key, ne[address] = next;
    }

    vector<int> a, b, c;
    for (int i = h; i != -1; i = ne[i])
    {
        int v = e[i];
        if (v < 0) a.push_back(i);
        else if (v <= k) b.push_back(i);
        else c.push_back(i);
    }

    a.insert(a.end(), b.begin(), b.end());
    a.insert(a.end(), c.begin(), c.end());

    for (int i = 0; i < a.size(); i ++ )
    {
        printf("%05d %d ", a[i], e[a[i]]);
        if (i + 1 == a.size()) puts("-1");
        else printf("%05d\n", a[i + 1]);
    }

    return 0;
}

你可能感兴趣的:(链表,数据结构,算法)