今天做算法笔记上的题目又碰到了反转链表。题目不难,但是写起来就是感觉脑子有点绕,也可能只是我水平太差的原因。
这已经是我第三次碰到这道题了,第一次是大一下开学期末考的时候,当时在机房写了一个多小时,我自己测试都是对的,而且基本上考虑到了所有的情况,但是每次提交都有几个测试点通不过,甚至还换了一种方法重新写了一遍还是不过,当时真的感觉心态有点崩了。
考完了之后还是不服,把题目重新看了一下,才发现题目上说是带有头结点的链表。。。我真的是要脑溢血了,上课的时候老师还在强调不要用头结点,平时作业也没有用过头结点,考试的时候出一道带有头结点的题,我根本没注意到。不过这样也好,从此以后看题目就更加注重这种细节了。
第二次写这题是上个学期后半学期没事练算法题的时候写到的。当时还没有写过静态链表,看到这道题目可以这样做就自己试了一下。虽然是写过,但是换一种方法就感觉是完全不一样的题目了,当时也是写了很久,画满了半张草稿纸。虽然最后代码量不大,但是写这种链表题总是感觉很绕。
今天是第三次写到这道题了,在书上学到了另外一种方法,就是把整个表示静态链表的数组进行排序,然后只要倒着输出就行了,太妙了。
1074 Reversing Linked List (25point(s))
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.
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:
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.
1 2 3 4 5 6 7 00100 6 4 00000 4 99999 00100 1 12309 68237 6 -1 33218 3 00000 99999 5 68237 12309 2 33218
Sample Output: 1 2 3 4 5 6 00000 4 33218 33218 3 12309 12309 2 00100 00100 1 99999 99999 5 68237 68237 6 -1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <iostream> #include <algorithm> using namespace std;const int maxn = 100010 ;struct Node { int address, data, next; int order = maxn; }node[maxn]; bool cmp (Node a, Node b) ;int main (int argc, const char * argv[]) { int begin, n, k, address; scanf ("%d%d%d" , &begin, &n, &k); for (int i = 0 ; i < n; i++) { scanf ("%d" , &address); scanf ("%d%d" , &node[address].data, &node[address].next); node[address].address = address; } int p = begin, count = 0 ; while (p != -1 ) { node[p].order = count++; p = node[p].next; } sort (node, node + maxn, cmp); n = count; for (int i = 0 ; i < n / k; i++) { for (int j = (i + 1 ) * k - 1 ; j > 1 ; j--) printf ("%05d %d %05d\n" , node[j].address, node[j].data, node[j - 1 ].address); printf ("%05d %d " , node[i * k].address, node[i * k].data); if (i < n / k - 1 ) printf ("%05d\n" , node[(i + 2 ) * k - 1 ].address); else { if (n % k == 0 ) printf ("-1\n" ); else { printf ("%05d\n" , node[(i + 1 ) * k].address); for (int i = n / k * k; i < n; i++) { printf ("%05d %d " , node[i].address, node[i].data); if (i < n - 1 ) printf ("%05d\n" , node[i + 1 ].address); else printf ("-1\n" ); } } } } return 0 ; } bool cmp (Node a, Node b) { return a.order < b.order; }
这种方法也是今天第一次学到,给我的最大的感触就是我以前写题目太老实了,可以从很多的角度来看题目,换一种方法直接边水题。
顺便写一下我以前写这道题的代码,我自我感觉还是写的不错的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include <iostream> #include <cstdlib> using namespace std;struct Node { int data; int next; }List[100001 ]; void Reversing (int start, int K) ;int main (int argc, const char *argv[]) { int First, N, K; scanf ("%d%d%d" , &First, &N, &K); for (int i = 0 ; i < N; i++) { int add; scanf ("%d" , &add); scanf ("%d%d" , &List[add].data, &List[add].next); } List[100000 ].next = First; Reversing (100000 , K); int p = List[100000 ].next; while (p != -1 ) { printf ("%05d %d " , p, List[p].data); if (List[p].next == -1 ) printf ("%d\n" , List[p].next); else printf ("%05d\n" , List[p].next); p = List[p].next; } return 0 ; } void Reversing (int start, int K) { int p, cnt = 0 ; p = List[start].next; cnt = 0 ; while (p != -1 ) { p = List[p].next; cnt++; if (cnt == K) { int q1, q2, tmphead = List[start].next; q2 = List[start].next; q1 = List[q2].next; for (int i = 0 ; i < K - 1 ; i++) { int tmp = List[q1].next; List[q1].next = q2; q2 = q1; q1 = tmp; } List[List[start].next].next = q1; List[start].next = q2; start = tmphead; cnt = 0 ; } } }