PAT02-1Reversing Linked List (25) 单链表逆序

02-1. Reversing Linked List (25)

http://www.patest.cn/contests/mooc-ds/02-1

时间限制  400 ms  内存限制   65536 kB   代码长度限制  8000 B  判题程序  Standard  作者CHEN, Yue

Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K = 3, then you must output 3→2→1→6→5→4; if K = 4, you must output 4→3→2→1→5→6.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (<= 105) which is the total number of nodes, and a positive K (<=N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

Output Specification:

For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

题目大意:反转单链表,给定常数K和单链表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.

输入说明:每次输入一个案例,对每个案例,第一行内容是链表第一个节点的地址,节点数N(N<=100,000)(不一定是最终形成的单链表的节点数),常数K(<=N),K是需要反转的子链表的长度,节点的地址是一个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

------------------------------------------------------------------------------

分析: 第一行:00100 表示第一个节点的位置,即节点: 00100 1 12309 然后根据12309找到第二个节点:12309 2 33218,继续找,直到找到最后一个节点 68237 6 -1。
形成的单链表是 1 -> 2 -> 3 -> 4 -> 5 -> 6。 第一行第二个数N=6,代表接下来会输入6个节点,K=4,意思是每4个节点逆转,余下2个节点,不足4个,故不反转。输出 4->3->2->1->5->6。

需要注意的是:1,如果K=1,链表不反转,K等于链表的节点数,链表整个反转,如果链表的节点数能被K整除,则每段都要反转。还有就是输出的时候节点的Next 是和逆转后的节点相关,不是原先节点的Next,如:输入的时候 节点 00000 4 99999 输出的时候应为 00000 4 33218,应为反转后节点4的下一个节点为3,而3的Address是33218。

------------------------------------------------------------------------------

life is short, show the code! C(gcc 4.7.2)
#include<stdio.h>
#define MAX_SIZE 100004

typedef struct tagLNode{
    int addr;      //节点位置Address
    int data;      //Data值
    int nextAddr;  //下个节点位置
    struct tagLNode *next;  //指向下个节点的指针
} LNode;
/*
    LNode *listReverse(LNode *head, int k);  
    反转单链表函数
    参数1:单链表的头节点,
    参数2:反转子链表的长度,
    返回值:反转后的链表的第一个节点(不是头结点)

*/
LNode *listReverse(LNode *head, int k);  
//输出单链表 参数为单链表的头结点
void printList(LNode *a);

int main()
{
    int firstAddr;
    int n = 0;            //节点数 N
    int k = 0;            //反转子链表的长度K
    int num = 0;          //链表建好之后的链表节点数
    int data[MAX_SIZE];   //存data值 节点位置作为索引值
    int next[MAX_SIZE];   //存next值 节点位置为索引
    int tmp;              //临时变量,输入的时候用
    
    scanf("%d %d %d", &firstAddr, &n, &k);    
    LNode a[n+1];                //能存n+1个几点的数组。
    a[0].nextAddr = firstAddr;   //a[0] 作为头节点
    //读输入的节点
    int i = 1;    
    for (; i < n+1; i++){
        scanf("%d", &tmp);
        scanf("%d %d", &data[tmp], &next[tmp]);        
    }
    
    //构建单链表
    i = 1;
    while (1){
        if (a[i-1].nextAddr == -1){
            a[i-1].next = NULL;
            num = i-1;
            break;            
        }
        a[i].addr = a[i-1].nextAddr;
        a[i].data = data[a[i].addr]; 
        a[i].nextAddr = next[a[i].addr];
        a[i-1].next = a+i;
                
        i++;
    }
    
    LNode *p = a;                    //p指向链表头结点
    LNode *rp = NULL;                //反转链表函数的返回值
    if (k <= num ){
        
        for (i = 0; i < (num/k); i++){
            rp = listReverse(p, k);  //
            p->next = rp;            // 第一次执行,a[0]->next 指向第一段子链表反转的第一个节点
            p->nextAddr = rp->addr;  // 更改Next值,指向逆转后它的下一个节点的位置
            
            int j = 0;
            //使p指向下一段需要反转的子链表的头结点(第一个节点的前一个节点)
            while (j < k){
                p = p->next;
                j++;
            }
        
        }
    }

    printList(a);    
}

LNode *listReverse(LNode *head, int k)
{
    int count = 1;
    LNode *new = head->next;
    LNode *old = new->next;
    LNode *tmp = NULL;
    
    while (count < k){
        tmp = old->next;
        old->next = new;
        old->nextAddr = new->addr;
        new = old;   //new向后走一个节点
        old = tmp;   //tmp向后走一个节点
        count++;
    }
    //使反转后的最后一个节点指向下一段子链表的第一个节点
    head->next->next = old;  
    if (old != NULL){
        //修改Next值,使它指向下一个节点的位置
        head->next->nextAddr = old->addr; 
    }else{
        //如果old为NULL,即没有下一个子链表,那么反转后的最后一个节点即是真个链表的最后一个节点
        head->next->nextAddr = -1;       
    }
    return new;
}

void printList(LNode *a)
{
    LNode *p = a;
    
    while (p->next != NULL){
        p = p->next;        
        if (p->nextAddr != -1 ){
            //格式输出,%.5意味着如果一个整数不足5位,输出时前面补0 如:22,输出:00022
            printf("%.5d %d %.5d\n", p->addr, p->data, p->nextAddr);
        }else{
            //-1不需要以%.5格式输出
            printf("%.5d %d %d\n", p->addr, p->data, p->nextAddr);
        }    
    }

}

测试点一共有7个: L 代表单链表节点数,因为构成单链表的节点不一定都在输入的N个节点中,即:L<=N;

case 0:L = N    有节点 Address = 99999

case 1: L = m*K,  L = N, (m = 2, 3, 4,...)  有节点 Address = 99999

case 2: K = N,  L = N      有节点 Address = 99999

case 3: K = 1,  L = m*K   有节点 Address = 99999

case 4: K = 1,  L = N = 1       (很简单的一个测试点)

case 5: K != 1, L % K = (K-1)   (节点数很多,如果建链表的复杂度是O(n*n), 超时的可能性很大)

case 6: L > N (有多余节点)  有节点Address = 99999


要考虑的细节:K=1不反转,K=L 全反转,L%K == 0, 每段都反转,L%k = (K-1),多余的节点不反转。L<N,有多余节点的情况。






posted @ 2015-02-10 13:51 德胜刘 阅读(7567) 评论(7) 推荐(0) 编辑

C++ Primer 学习笔记

摘要: 迭代器iteratorconst_iterator 只能读取容器内的元素,但是不能修改其值。例如要遍历输出vector类型的text中的元素,因为不需要修改元素值,可以用下面的方法来输出。// use const_iterator because we won't change elementsfor (vector::const_iterator iter = text.begin(); iter != text.end(); ++iter) cout::iterator mid= vi.begin() + vi.end()/2 直接定位于vector的中间元素标准库bitset​​ 阅读全文
posted @ 2013-08-01 10:11 德胜刘 阅读(258) 评论(0) 推荐(0) 编辑

闷热的北京

摘要: 7月份大学毕业后就从呼和浩特来到北京,开始我的北漂生活,在上地佳园两个星期之后就搬到西二旗了,终于算是安定下来了。 7月3号学校举行毕业典礼,本以为可以在3号拿到毕业证学位证直接来北京,事实说明在办事效率上,我们学校绝对不怎么样,终于5号上午拿到了大学四年时间换来的两个本本。说实话,内心还是有... 阅读全文
posted @ 2013-07-30 21:22 德胜刘 阅读(183) 评论(0) 推荐(0) 编辑

营销再华丽,也别忘了这8条!

摘要: ①营销的根本是卖东西;②让你的品牌成为一个故事;③用消费者的语言对话;④创造一种体验或期待,而不仅仅是商品;⑤别试图控制社交媒体和别人的言论;⑥相信消费者体验,而不是市调结论;⑦和新用户一起变化,和老用户一起长情;⑧便宜的产品不等于差劲的设计. 阅读全文
posted @ 2012-12-18 11:55 德胜刘 阅读(122) 评论(0) 推荐(0) 编辑

和喜欢的人一起工作

摘要: 一定不要和不喜欢的人一起工作。 有这么句话,小公司做事,大公司做人。我估摸着意思大概是说大公司更注重员工个人素质的培养什么的。小公司则要对员工个人的问题关注的少一些。我个人倒是觉得,想要做大事,成就大事业,人才是第一生产力。不管是小公司还是大公司,没有员工来完成工作,一切都扯淡。即使领导能力再... 阅读全文
posted @ 2012-12-17 14:57 德胜刘 阅读(303) 评论(0) 推荐(0) 编辑

年会有所思

摘要: 昨天晚上,呼啦圈网站年会,没想到会有那么多的人,因为相同的爱好与追求走到一起,无论是网站的元老还是刚加入团队不久的新人,彼此攀谈,交流感情。想想加入呼啦圈这段时间,从对站长周哥一无所知到成为关系密切的挚友,不到一年时间,我感受到的是那种无话不说,有啥事直接交代就可以的信任感。而更让我感到亲切的是周哥那种对兄弟,对朋友的无私,那种两肋插刀的义气。如此挚友,当一世珍惜。 阅读全文
posted @ 2012-12-16 20:41 德胜刘 阅读(132) 评论(0) 推荐(0) 编辑

关于设计的思考-观看ted台北设计师演讲之后的感想

摘要: 昨天晚上在新浪微博上看到一个视频,ted演讲,演讲者是台北的一个设计师,讲了他对设计行业的理解于认识,视频的题目是《为什么设计师不受到尊重? 学设计的同学都看看吧,确实是这样的》,他讲了两个案例,一个是他们公司附近的一个咖啡厅,logo很漂亮,但倒闭了,另一个是旺旺的logo,他说旺旺的logo算是世界上最丑的logo之一了吧,但是旺旺一年有226亿的营收。所以说logo的漂亮与否对一个企业来说几乎不起作用。logo本身并不能影响到一个企业的成败,所以作为设计师,还得学会别的东西,等你吧营销,人力,各方面都学的差不多了,你就牛了,因为别人会的你都会,你还会设计。包益民在TED上的演讲--A.. 阅读全文
posted @ 2012-12-14 09:24 德胜刘 阅读(443) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示