PAT02-1Reversing Linked List (25) 单链表逆序
2015-02-10 13:51
357 查看
02-1. Reversing Linked List (25)
http://www.patest.cn/contests/mooc-ds/02-1时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者CHEN, YueGiven 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 Nextwhere 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 = 99999case 1: L = m*K, L = N, (m = 2, 3, 4,...) 有节点 Address = 99999case 2: K = N, L = N 有节点 Address = 99999case 3: K = 1, L = m*K 有节点 Address = 99999case 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,有多余节点的情况。
相关文章推荐
- PAT (Advanced Level) 1097. Deduplication on a Linked List (25) 链表去重
- PAT甲级题解-1097. Deduplication on a Linked List (25)-链表的删除操作
- leetcode——Reverse Linked List II 选择链表中部分节点逆序(AC)
- LeetCode OJ 之 Reverse Linked List (链表逆序)
- PAT 1133. Splitting A Linked List (25) 链表的拆分和合并
- PAT - 甲级 - 1074. Reversing Linked List (25)(链表)
- 1025. 反转链表 (25)PAT乙级&&1074. Reversing Linked List (25)PAT甲级
- PAT 1097. Deduplication on a Linked List (25)(链表问题)(链表分段)
- PAT 1097. Deduplication on a Linked List (25) 剔除链表中的重复节点,set用法,尾插法
- leetcode——Reverse Linked List II 选择链表中部分节点逆序(AC)
- 1133. Splitting A Linked List (25)[链表处理]
- 92. Reverse Linked List II(链表局部逆序**)
- 关于线性表的两种储存结构及单链表逆序解析(ArrayList和LinkedList)
- pat甲级1074. Reversing Linked List (25)、乙级1025. 反转链表 (25)
- PAT甲题题解-1074. Reversing Linked List (25)-求反向链表
- PAT - 甲级 - 1097. Deduplication on a Linked List (25)(链表)
- 1074. Reversing Linked List (25)【链表翻转】——PAT (Advanced Level) Practise
- leetcode | 单链表逆序 Reverse Linked List
- LeetCode 25 Reverse Nodes in k-Group(在K组链表中反转结点)(Linked List)(*)
- PAT 1074. Reversing Linked List (25)(链表反转)