首页 > 代码库 > PAT-1074
PAT-1074
首先先贴一下题目:
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 400000 4 9999900100 1 1230968237 6 -133218 3 0000099999 5 6823712309 2 33218
Sample Output:
00000 4 3321833218 3 1230912309 2 0010000100 1 9999999999 5 6823768237 6 -1
输入:
第一行:链表的首地址add,结点个数n,每隔k个进行一次反转。
接下来的n行:结点的地址address,数据data,下一个结点的地址next。
输出:
反转之后的结果。
建议测试如下几个情况:
1. k=1或者k=n:
00100 6 6
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
2. 有其他链表干扰(即有多个-1出现):
00100 6 2
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 -1
99999 5 68237
12309 2 33218
先说一下我的解题思路吧。
1. 首先要处理输入数据。我是用C++中的容器(vector),容器内存储的类型是新建的类Node。
1 class Node 2 { 3 public : 4 int address; 5 int data; 6 int next; 7 Node* nextNode; 8 Node(int a = 0, int d = 0, int n = 0): 9 address(a), data(d), next(n)10 {11 nextNode = NULL;12 }13 };14 int main()15 {16 int add, n, k;17 cin >> add >> n >> k;18 vector<Node> vec;19 // input the data20 for(int i=0; i<n; i++)21 {22 int inputa, inputb, inputc;23 cin >> inputa >> inputb >> inputc;24 Node node(inputa, inputb, inputc);25 vec.push_back(node);26 }27 // ...28 }
2. 这里首先要进行一个预处理,就是按照address对vector内的数据进行升序排序。这么做是为了能增快程序的运行速度,以便通过测试用例5。
1 // define before main2 bool cmp(const Node &a,const Node &b)3 {4 return a.address < b.address;5 }6 int main(){7 // ...8 sort(vec.begin(), vec.end(), cmp);9 }
3. 然后要处理数据,把vecotr内的数据组成单链表。ncount是链表有效结点的数目,p用来遍历myList,q用来遍历myNewList(即反转后的链表)。处理的过程如下:在vector内不断的寻找address为add(即链表头),找到之后放到MyList,然后让it->next成为新的add。不断重复此过程,直到it->next为-1(即链表尾)为止。上面的预处理在这里就起到作用了,如果没有按照address进行升序排序,这个过程会很慢,通不过测试用例。
用while(1)循环,并且当it走到vector的end再让它回到begin,成一个环状。一定会有it->next为-1走出循环,所以不必担心死循环问题。
1 Node* myList = new Node(); 2 int ncount = 0; 3 Node *p = NULL; 4 Node *q = NULL; 5 // deal the data from vector to list 6 vector<Node>::iterator it = vec.begin(); 7 while(1) 8 { 9 // find the first node10 if(it->address == add)11 {12 if(myList->nextNode == NULL)13 {14 p = myList->nextNode = new Node(it->address, it->data, it->next);15 }16 else17 {18 p = p -> nextNode = new Node(it->address, it->data, it->next);19 }20 ncount ++;21 if(it -> next == -1)22 break;23 else24 add = it -> next;25 }26 it++;27 if(it == vec.end())28 it = vec.begin();29 }// for
4. 接下来就是反转了,具体的我已经写到注释里了,如果有看不懂的地方可以再评论区里发表评论。
1 // if the k greater than effective data, then output all 2 if(k>ncount) 3 { 4 p = myList; 5 while(p->nextNode != NULL) 6 { 7 p = p -> nextNode; 8 if(p->next != -1) 9 printf("%.5d %d %.5d\n", p->address, p->data, p->next);10 else11 printf("%.5d %d -1\n", p->address, p->data);12 }13 }// if14 else15 {16 Node *myNewList = new Node();17 // 借助栈来完成反转18 stack<Node*> sta;19 // 需要反转几次20 int times = ncount/k;21 // p始终指向MyList22 p = myList;23 // q始终指向MyNewList24 q = myNewList;25 // 进行times次反转26 for(int j=0; j<times; j++)27 {28 for(int m=0; m<k; m++)29 {30 p = p -> nextNode;31 sta.push(p);32 }33 for(int m=0; m<k; m++)34 {35 Node *qt = sta.top();36 sta.pop();37 if(myNewList->nextNode == NULL)38 {39 q = myNewList->nextNode = new Node(qt->address, qt->data, qt->next);40 }41 else42 {43 q = q -> nextNode = new Node(qt->address, qt->data, qt->next);44 }45 }46 } // for47 // 将剩下的节点依次插入到myNewList后面48 while(p -> nextNode != NULL)49 {50 p = p -> nextNode;51 if(myNewList->nextNode == NULL)52 {53 q = myNewList->nextNode = new Node(p->address, p->data, p->next);54 }55 else56 {57 q = q -> nextNode = new Node(p->address, p->data, p->next);58 }59 } // while60 // 输出61 p = myNewList;62 while(p->nextNode != NULL)63 {64 p = p -> nextNode;65 if (p->nextNode != NULL)66 p->next = p->nextNode -> address;67 else68 p->next = -1;69 if(p->next != -1)70 printf("%.5d %d %.5d\n", p->address, p->data, p->next);71 else72 printf("%.5d %d -1\n", p->address, p->data);73 } // while
5. 完整的代码如下:
1 #include <iostream> 2 #include <vector> 3 #include <cstdlib> 4 #include <iomanip> 5 #include <cstdio> 6 #include <stack> 7 #include <algorithm> 8 using namespace std; 9 10 class Node 11 { 12 public : 13 int address; 14 int data; 15 int next; 16 Node* nextNode; 17 Node(int a = 0, int d = 0, int n = 0): 18 address(a), data(d), next(n) 19 { 20 nextNode = NULL; 21 } 22 }; 23 bool cmp(const Node &a,const Node &b) 24 { 25 return a.address < b.address; 26 } 27 int main() 28 { 29 int add, n, k; 30 cin >> add >> n >> k; 31 vector<Node> vec; 32 // input the data 33 for(int i=0; i<n; i++) 34 { 35 int inputa, inputb, inputc; 36 cin >> inputa >> inputb >> inputc; 37 Node node(inputa, inputb, inputc); 38 vec.push_back(node); 39 } 40 sort(vec.begin(), vec.end(), cmp); 41 Node* myList = new Node(); 42 int ncount = 0; 43 Node *p = NULL; 44 Node *q = NULL; 45 // deal the data from vector to list 46 vector<Node>::iterator it = vec.begin(); 47 while(1) 48 { 49 // find the first node 50 if(it->address == add) 51 { 52 if(myList->nextNode == NULL) 53 { 54 p = myList->nextNode = new Node(it->address, it->data, it->next); 55 } 56 else 57 { 58 p = p -> nextNode = new Node(it->address, it->data, it->next); 59 } 60 ncount ++; 61 if(it -> next == -1) 62 break; 63 else 64 add = it -> next; 65 } 66 it++; 67 if(it == vec.end()) 68 it = vec.begin(); 69 }// for 70 // if the k greater than effective data, then output all 71 if(k>ncount) 72 { 73 p = myList; 74 while(p->nextNode != NULL) 75 { 76 p = p -> nextNode; 77 if(p->next != -1) 78 printf("%.5d %d %.5d\n", p->address, p->data, p->next); 79 else 80 printf("%.5d %d -1\n", p->address, p->data); 81 } 82 }// if 83 else 84 { 85 Node *myNewList = new Node(); 86 // 借助栈来完成反转 87 stack<Node*> sta; 88 // 需要反转几次 89 int times = ncount/k; 90 // p始终指向MyList 91 p = myList; 92 // q始终指向MyNewList 93 q = myNewList; 94 // 进行times次反转 95 for(int j=0; j<times; j++) 96 { 97 for(int m=0; m<k; m++) 98 { 99 p = p -> nextNode;100 sta.push(p);101 }102 for(int m=0; m<k; m++)103 {104 Node *qt = sta.top();105 sta.pop();106 if(myNewList->nextNode == NULL)107 {108 q = myNewList->nextNode = new Node(qt->address, qt->data, qt->next);109 }110 else111 {112 q = q -> nextNode = new Node(qt->address, qt->data, qt->next);113 }114 }115 } // for116 // 将剩下的节点依次插入到myNewList后面117 while(p -> nextNode != NULL)118 {119 p = p -> nextNode;120 if(myNewList->nextNode == NULL)121 {122 q = myNewList->nextNode = new Node(p->address, p->data, p->next);123 }124 else125 {126 q = q -> nextNode = new Node(p->address, p->data, p->next);127 }128 } // while129 // 输出130 p = myNewList;131 while(p->nextNode != NULL)132 {133 p = p -> nextNode;134 if (p->nextNode != NULL)135 p->next = p->nextNode -> address;136 else137 p->next = -1;138 if(p->next != -1)139 printf("%.5d %d %.5d\n", p->address, p->data, p->next);140 else141 printf("%.5d %d -1\n", p->address, p->data);142 } // while143 }// else144 return 0;145 }
困扰我两周的难题终于解决了,试验了20多次将近30次,有图为证:
最后再粘一下AC的成果:
PAT-1074