标签:des style blog io ar color os sp for
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 33218Sample Output:
00000 4 33218 33218 3 12309 12309 2 00100 00100 1 99999 99999 5 68237 68237 6 -1
【solution】
初看题意,很简明易懂。(不要被表象迷惑了。。
链表嘛,还手动给出了节点地址,于是开始写。
等我经历了一番折腾之后,我觉得这道题堪称打表审题,因为它实在是把这个点用表象隐藏得很好。想明白了之后实现就并不难了。
说下我的“心路历程”:
很快发现这题的关键在于“段与段”之间的“地址”连接处要处理好。
一开始,特意用结构体来构造出节点,三个成员,data, addr(自己的地址),next(下一个节点地址),其中地址用字符串来存储,然后创造一个元素是结构体的数组(得强调一下物理地址是相邻的一块内存)。
很自然的,我开始用输入数据构造一个串。怎么构造呢?地址都是字符串,又很自然的,随手开始暴力查找下一个节点,显然是个O(n^2)的。然后想,我擦,不会过不了吧。有优化吗?一时并没有想到(与字符串存地址的先入思维有关)。
然后想,唉这才第二周第一道题,测试数据应该不会很坑吧。(事实上我已经掉坑里了 T_T)
然后写完一测试,一个点超时,一个点竟然还WA了!超时还可以理解,竟然还有WA!
然后首先开始解决WA的问题(因为超时可能也是程序对某些测例出错引起的)。再看代码,边界情况应该都没有问题啊。
在讨论区受陈越姥姥提醒,输入数据中的节点竟然有可能不在有效的需要输出的链上!也就是最后输出的链长可能没有 n !因为输入里面有无效节点!T_T
姥姥(出题人)真是心思缜密啊![苦笑]
然后WA解决了,可是还是有超时。
看来问题是出在 O(n^2) 的构造链上。
再看代码,觉得可能是地址复制来复制去的字符串操作影响了效率,这才终于开始思考把地址用整型来存储。
马上把地址改成了整型,还是超时。
问姥姥,姥姥说是有点小技巧,复杂度是 O(n) 的。
竟然是 O(n) 的!!我才开始认真思考起优化来。
是不是要排序啊?给地址排个序然后二分查找?即便如此也是 O(nlogn) 啊。而且第二周诶,还没讲诶,不会这么复杂吧。[再次苦笑]
开始还一直桎梏于地址为字符串的思路里,甚至想到了 哈希表、优先级队列、完全二叉堆 等等数据结构。可是这才第二周啊![大声苦笑加自嘲]
大概是习惯了打表对于大多数题肯定不会是标准解法,其原因在于题目数据范围一般较大,慢慢的忘了“初心”了。[骗分导论加苦笑!]
这道题真的隐藏得很好,姥姥真是有心了。
思维经历一番千回百转的浪潮,终于想到了将地址作为数组的数值下标,而数组值是数据内容以及下一个节点地址这种被我称作“打表”的办法。
不禁一阵唏嘘啊 T_T
有几点要说:
1、不要小看任何一道题;
2、这道题真正巧妙的揭示了列表和向量的区别与本质,看似题目是列表,实际做起来却是向量;
3、代码中,输出前导0的格式控制:%05d。向右对齐,最少占5位,不足用0填补。
AC代码如下,可能空间上还可以优化,由于我为了竟可能少改动原始版的代码就做不做大幅改动了:
1 #include <stdio.h> 2 #include <malloc.h> 3 4 #define AddrMAX 1000004 5 6 typedef struct AnsNode 7 { 8 int addr, data; 9 }anode, *panode; 10 11 int main(void) 12 { 13 int n, k, i, j, block, rest, top = 0; 14 int start, temp; 15 16 scanf("%d %d %d", &start, &n, &k); 17 18 int* data = (int *)malloc(sizeof(int)*(AddrMAX)); 19 int* next = (int *)malloc(sizeof(int)*(AddrMAX)); 20 21 panode ans = (panode)malloc(sizeof(anode)*(n+1)); 22 23 for (i = 0; i < n; i++) 24 { 25 scanf("%d", &temp); 26 scanf("%d %d", &data[temp], &next[temp]); 27 } 28 29 // 按地址将链构造好放入ans中 30 while (start != -1) 31 { 32 ans[top].data = data[start]; 33 ans[top].addr = start; 34 start = next[start]; 35 top++; 36 } 37 n = top; 38 39 // 每 K 段输出一次,并且处理最后一次不足k个的情况,关键点在于“段与段”之间“地址 ”的拼接 40 block = n / k; rest = n % k; 41 for (j = 0; j < block; j++) 42 { 43 for (i = (j + 1)*k - 1; i > j*k; i--) 44 { 45 printf("%05d %d %05d\n", ans[i].addr, ans[i].data, ans[i-1].addr); 46 } 47 printf("%05d %d ", ans[i].addr, ans[i].data); 48 if (rest == 0) 49 { 50 if (j == block - 1) printf("-1"); 51 else printf("%05d", ans[(j+2)*k-1].addr); 52 } else 53 { 54 if (j == block - 1) printf("%05d", ans[(j+1)*k].addr); 55 else printf("%05d", ans[(j+2)*k-1].addr); 56 } 57 printf("\n"); 58 } 59 if (rest != 0) 60 { 61 for (i = block*k; i < n - 1; i++) printf("%05d %d %05d\n", ans[i].addr, ans[i].data, ans[i+1].addr); 62 printf("%05d %d -1\n", ans[i].addr, ans[i].data); 63 } 64 65 return 0; 66 }
【Zhejiang University PATest】02-1. Reversing Linked List
标签:des style blog io ar color os sp for
原文地址:http://www.cnblogs.com/maples7/p/4153984.html