PAT Basic 反转链表 (25) [链表]

题目

给定⼀个常数K以及⼀个单链表L,请编写程序将L中每K个结点反转。例如:给定L为1→2→3→4→5→6,K为3,则输出应该为3→2→1→6→5→4;如果K为4,则输出应该为4→3→2→1→5→6,即最后不到K个元素不反转。
输⼊格式:
每个输⼊包含1个测试⽤例。每个测试⽤例第1⾏给出第1个结点的地址、结点总个数正整数N(<= 10^5)、以及正整数K(<=N),即要求反转的⼦链结点的个数。结点的地址是5位⾮负整数,NULL地址⽤-1表示。
接下来有N⾏,每⾏格式为:

Address Data Next

其中Address是结点地址,Data是该结点保存的整数数据,Next是下⼀结点的地址。
输出格式:
对每个测试⽤例,顺序输出反转后的链表,其上每个结点占⼀⾏,格式与输⼊相同。
输⼊样例:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
输出样例:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

题目分析

已知N个结点,以K为步长,反转链表

解题思路

  1. 定义结点,使用数组存储N个结点,使用order属性记录链表中结点出现序号
  2. 将链表分为n/k个段,对每个段进行反转
    2.1 每个节点的next即为反转后的下一个结点地址
    2.2 每个段最后一个节点的特殊处理:next为下一个段反转前最后一个结点
    2.3 最后一个段的处理
    • 若n%k==0,说明n可以正好分为n/k个段,最后一个段反转,并将最后一个节点置为-1
    • 若n%k!=0,说明最后一段小于k,开始下标为n/k*k,不需要反转,顺序打印,并将最后一个结点置为-1

知识点

  1. 将n个结点分为n/k个段,最后一段开始下标为n/k*k(下标从0开始)
  2. 链表反转,不一定非要对链表进行反转(即:更换每个结点next值),可以使用本题思想反向打印的办法

易错点

  1. 已知结点中,有不存在与链表上的无效结点

Code

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100010;
struct node {
    int adr;
    int data;
    int next;
    bool flag=false;//初始化为false
    int order=maxn;
} nds[maxn];
bool cmp(node &n1,node &n2) {
    return n1.order<n2.order;
}
int main(int argc,char *argv[]) {
    int hadr,n,k,adr;
    scanf("%d %d %d",&hadr,&n,&k);
    for(int i=0; i<n; i++) {
        scanf("%d",&adr);
        scanf("%d %d",&nds[adr].data,&nds[adr].next);
        nds[adr].adr=adr;
    }
    int count=0;
    for(int i=hadr; i!=-1; i=nds[i].next) {
//      nds[i].flag=true;
        nds[i].order=count++;
    }
    sort(nds,nds+maxn,cmp);
    n=count;
//  for(int i=0; i<n; i++) {
//      printf("%05d %05d %05d\n",nds[i].adr,nds[i].data,nds[i].next);
//  }
    for(int i=0; i<n/k; i++) {
        for(int j=(i+1)*k-1; j>i*k; j--) {
            printf("%05d %d %05d\n",nds[j].adr,nds[j].data,nds[j-1].adr);
        }
        printf("%05d %d",nds[i*k].adr,nds[i*k].data);
        if(i<n/k-1) {
            printf(" %05d\n",nds[(i+2)*k-1].adr);
        } else {
            if(n%k==0)printf(" -1\n"); //正好可以分为n/k块,并且打印最后一块
            else {
                printf(" %05d\n",nds[(i+1)*k].adr);
                for(int j=n/k*k; j<n; j++) {
                    printf("%05d %d",nds[j].adr,nds[j].data);
                    if(j<n-1)printf(" %05d\n",nds[j+1].adr);
                    else printf(" -1\n");
                }
            }
        }
    }
    return 0;
}


猜你喜欢

转载自www.cnblogs.com/houzm/p/12296864.html