码迷,mamicode.com
首页 > 其他好文 > 详细

【Zhejiang University PATest】02-1. Reversing Linked List

时间:2014-12-09 21:19:43      阅读:309      评论:0      收藏:0      [点我收藏+]

标签: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 33218
Sample 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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!