PAT (Basic Level) Practice (中文)- 1025 反转链表(25 分)

题目链接1:点击打开链接 

题目链接2:点击打开链接 

题目大意:略。

解题思路:

1、输入初始化
2、从头走到尾一遍,统计有效个数,并把最后一个结点的 next = -1
3、从头开始,每 k 个反转链表并将反转后的结果传到最终输出的容器里(注意:不到 k 个无需反转,不要忘记把每段反转以后的新的链表接起来)
4、注意 k==1 的情况,有两个点(3、4 测试点)是搞这个的,我是自己特判处理的(因为无需反转)。换句话说:一是结点数能整除 K 的,二是不能整除的。当能整除时,一定注意调整最后的那个-1。以及 K 也有可能大于有效节点数。
5、考虑 cout、cin 容易超时的问题,用 scanf、printf 替代。
 

未 AC 代码(测试点5 WA,就是那组数据很大的那组,真不知道什么情况没考虑到~)

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

const int maxn=1e5+10;

struct node
{
    int id,cur,nx,pre;
}nds[maxn], ndrs[maxn];

int l, len, F;
node tnd;

void showInit(int h)
{
    puts("-----------------------");
    int cur=h;
    for(int i=0;i<len;i++)
    {
        printf("%05d %d %05d\n",nds[cur].cur,nds[cur].id,nds[cur].nx);
        cur=nds[cur].nx;
    }
    puts("-----------------------");
}

void reverseList(int s, int e)
{
    if(l>0) ndrs[l-1].nx=e;
    int cur=e,pre,jde=nds[s].pre;
    while(1)
    {
        pre=nds[cur].pre;
        nds[cur].nx=pre;

        ndrs[l++]=nds[cur];
        if(jde==pre) return;
        cur=pre;
    }
}

int main()
{
    int h,n,k;
    while(~scanf("%d%d%d",&h,&n,&k))
    {
        int cur,id,nx;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d",&cur,&id,&nx);
            nds[cur].id=id, nds[cur].cur=cur, nds[cur].nx=nx;
        }

//        if(h==-1){ puts("-1"); continue; }

        // 从头走到尾一遍,统计有效个数,并把它们各自的前置地址找到,以及把最后一个结点的 next = -1
        int pre=-2;
        cur=h; len=0;
        int f=1;
        while(1)
        {
            nds[cur].pre=pre;
            pre=cur;
            cur=nds[cur].nx;
            len++; if(len==k) F=pre;
            if(cur==-1 || nds[cur].id==0)
            {
                nds[pre].nx=-1;
                break;
            }
        }

        if(len<k) k=1;
//        printf("Last == cur : %05d, nx : %d\n",pre,nds[pre].nx);
//        cout<<len<<endl;
//        showInit(h);

        // 从头开始,每 k 个反转链表并将反转后的结果传到最终输出的容器里(注意:不到 k 个无需反转,而且每次把上一组的衔接修复好)
        l=0; cur=h;
        int th, t=0, tcur;
        while(k!=1) // k==1 无需反转
        {
            cur=nds[cur].nx;
            t++;
            if(t==k-1 && cur!=-1)
            {
//                printf("h: %05d, t: %05d\n",h,cur);
                t=0;
                th=nds[cur].nx;
                reverseList(h,cur);
                tcur=cur=h=th;
//                show();
            }

            if(cur==-1) break;
        }

        if(len%k!=0) ndrs[l-1].nx=tcur; // 修复好最后一组未修复的
        while(len%k!=0 && tcur!=-1)
        {
            ndrs[l++]=nds[tcur];
            tcur=nds[tcur].nx;
        }

        if(k==1) // 特判
        {
            while(1)
            {
                ndrs[l++]=nds[cur];
                cur=nds[cur].nx;
                if(cur==-1) break;
            }
        }

        for(int i=0;i<l;i++)
        {
            if(i==len-1) printf("%05d %d -1\n",ndrs[i].cur,ndrs[i].id);
            else printf("%05d %d %05d\n",ndrs[i].cur,ndrs[i].id,ndrs[i].nx);
//            cur=ndrs[cur].nx;
        }

    }

    return 0;
}

/* 附赠一些有代表性的测试用例
00100 6 4
00000 4 99999
00100 1 12300
68288 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

00100 8 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
12345 7 45678
45678 8 98765

00100 2 1
00100 1 12309
12309 2 -1

-1 1 1
00100 1 -1

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 -1
99999 5 68237
12309 2 33218
*/

AC 代码

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

const int maxn=1e5+5;

int da[maxn], nx[maxn], a[maxn];

int main()
{
    int first,n,k,t,len;
    while(~scanf("%d%d%d",&first,&n,&k))
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",&t);
            scanf("%d%d",&da[t],&nx[t]);
        }

        len=0;
        while(first!=-1)
        {
            a[len++]=first;
            first=nx[first];
        }

        int times=len/k;
        for(int i=0,j=0; j<times; i+=k, j++)
            reverse(a+i,a+i+k);

        for(int i=0;i<len-1;i++)
            printf("%05d %d %05d\n",a[i],da[a[i]],a[i+1]);
        printf("%05d %d -1\n",a[len-1],da[a[len-1]]);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dream_Weave/article/details/81301445