PAT的链表题还算比较友好 ,大多用静态链表
在储存单词时,我们可以使用链表逐个字母进行储存。
为了节约空间,如果两个单词拥有共同的后缀,那么可以让它们共享一个相同的子链表。
例如,loading 和 being 可以如下图所示储存:

你需要找到共同后缀的起始位置。(对于上图,即为 ii 的位置)
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int N=1e5+233;
struct node {
char data;
int next;
}a[N];
int vis[N];
int main(){
int head,head1,n;
cin>>head>>head1>>n;
rep(i,0,n){
int id;
cin>>id;
cin>>a[id].data>>a[id].next;
}
int p=head;
while(p!=-1){
vis[p]=1;
p=a[p].next;
}
p=head1;
while(p!=-1){
if(vis[p]) {
printf("%05d",p);
return 0;
}
p=a[p].next;
}
puts("-1");
}
PAT1074 Reversing Linked List 反转链表
给定一个常数 KK 和一个单链表 LL,请你在单链表上每 K个元素做一次反转,并输出反转完成后的链表。
例如,假设 LL 为 1→2→3→4→5→6,如果 K=3,则你应该输出 3→2→1→6→5→4;如果 K=4,则你应该输出 4→3→2→1→5→6
补充
1、本题中可能包含不在链表中的节点,这些节点无需考虑。
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int N=1e5+233;
struct node {
int data,next;
}a[N];
int L[N],ans[N];
int main(){
int head,n,k;
cin>>head>>n>>k;
rep(i,0,n){
int id;
cin>>id;
cin>>a[id].data>>a[id].next;
}
int cnt=0;
int p=head;
while(p!=-1){
L[cnt++]=p;
p=a[p].next;
}
rep(i,0,cnt) ans[i]=L[i];
rep(i,0,cnt/k){
rep(j,0,k)
ans[i*k+j]=L[i*k+k-1-j];
}
rep(i,0,cnt-1)
printf("%05d %d %05d\n",ans[i],a[ans[i]].data,ans[i+1]);
printf("%05d %d -1\n",ans[cnt-1],a[ans[cnt-1]].data);
}
PAT 1097 Deduplication on a Linked List 链表重复数据删除
给定一个单链表 L,链表上的每个节点都存有一个键值,你应该删掉其中拥有重复键值绝对值的节点。
也就是说,对于每个值 K,只保留键值或键值绝对值为 K 的第一个节点。
同时,被删掉的节点也应保存在一个单独的链表中。
例如,给定 L 为 21→-15→-15→-7→15,则删除重复数据后的链表为 21→-15→-7,已删除链表为 -15→15。
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int N=1e5+233;
struct node {
int data;
int next;
}a[N];
int vis[N];
int L[N],del[N];
int main(){
int head,n;
cin>>head>>n;
rep(i,0,n){
int id;
cin>>id;
cin>>a[id].data>>a[id].next;
}
int cnt=0,tot=0;
int p=head;
while(p!=-1){
int t=fabs(a[p].data);
if(!vis[t]){
vis[t]=1;
L[cnt++]=p;
}
else{
del[tot++]=p;
}
p=a[p].next;
}
rep(i,0,cnt-1)
printf("%05d %d %05d\n",L[i],a[L[i]].data,L[i+1]);
printf("%05d %d -1\n",L[cnt-1],a[L[cnt-1]].data);
if(tot){
rep(i,0,tot-1)
printf("%05d %d %05d\n",del[i],a[del[i]].data,del[i+1]);
printf("%05d %d -1\n",del[tot-1],a[del[tot-1]].data);
}
}
PAT1133 Splitting A Linked List 链表元素分类
给定一个单链表,请编写程序将链表元素进行分类排列,使得所有负值元素都排在非负值元素的前面,而 [0,K][0,K] 区间内的元素都排在大于 K 的元素前面。
但每一类内部元素的顺序是不能改变的。
例如:给定链表为 18→7→-4→0→5→-6→10→11→-2,K 为 10,则输出应该为 -4→-6→-2→7→0→5→10→18→11。
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int N=1e5+233;
struct node {
int data;
int next;
}a[N];
int L[4][N];
int main(){
int head,n,k;
cin>>head>>n>>k;
rep(i,0,n){
int id;
cin>>id;
cin>>a[id].data>>a[id].next;
}
int cnt[4]={0};
int p=head;
while(p!=-1){
int t=a[p].data;
if(t<0){
L[1][cnt[1]++]=p;
}
else if(t<=k)
L[2][cnt[2]++]=p;
else
L[3][cnt[3]++]=p;
p=a[p].next;
}
vector<int>ans;
rep(i,1,4)
rep(j,0,cnt[i])
ans.push_back(L[i][j]);
rep(i,0,ans.size()-1){
printf("%05d %d %05d\n",ans[i],a[ans[i]].data,ans[i+1]);
}
printf("%05d %d -1\n",ans[ans.size()-1],a[ans[ans.size()-1]].data);
}

本文汇总了PAT考试中的四道链表题目,包括共享链表存储单词、反转链表、删除链表重复数据以及链表元素分类。通过实例解析,详细介绍了每道题目的解题思路和实现方法,帮助读者理解和掌握链表操作技巧。

1620

被折叠的 条评论
为什么被折叠?



