pat1052

来源:互联网 发布:java字节转为字符串 编辑:程序博客网 时间:2024/06/07 17:14

1052. Linked List Sorting (25)

时间限制
400 ms
内存限制
32000 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

A linked list consists of a series of structures, which are not necessarily adjacent in memory. We assume that each structure contains an integer key and a Next pointer to the next structure. Now given a linked list, you are supposed to sort the structures according to their key values in increasing order.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive N (< 105) and an address of the head node, where N is the total number of nodes in memory and the address of a node is a 5-digit positive integer. NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Key Next

where Address is the address of the node in memory, Key is an integer in [-105, 105], and Next is the address of the next node. It is guaranteed that all the keys are distinct and there is no cycle in the linked list starting from the head node.

Output Specification:

For each test case, the output format is the same as that of the input, where N is the total number of nodes in the list and all the nodes must be sorted order.

Sample Input:
5 0000111111 100 -100001 0 2222233333 100000 1111112345 -1 3333322222 1000 12345
Sample Output:
5 1234512345 -1 0000100001 0 1111111111 100 2222222222 1000 3333333333 100000 -1



first code , 错了两个测试点,一个是运行超时,另一个是答案错误,思考了一下, 
第一个运行超时应该是每次从存放读入元素的数组中,都要进行一次查找,使得 findLoc 方法的整体时间复杂度为 O(n)
并且在另一个时间复杂度为 O(N) 的循环中调用一个时间复杂度为 O(n) 的算法的话,使得方法 deal_的时间复杂度为 O(N^2)
并且本题目的时间限制是 400ms, N 取值最大值为 < 100000 大约为 99999  , O(N^2) 为 10^10 必定超时。
另一个答案是错误的,我觉得应该是,如果链表中如果只有一个元素节点满足题意的话,这种情况没有考虑好。

21/25

/**first read in all the nums into the list then find the head elements , and select it from the list and insert it into the first place of another list2 , and select from the list1 the element which head = x .end*/#include <cstdio>#include <cstdlib>#include <vector>#include <algorithm>using namespace std ;#define Max 1001struct node{int head, end ,key ;bool operator < ( const node &b ) const{return key < b.key ;}} ;vector<node>list1 ;int Num , head ;vector<node> list2 ; int len = 0 ;void getInput(){node temp ;scanf("%d%d", &Num , &head ) ;for ( int i = 0 ; i < Num ; i++ ){scanf("%d%d%d", &temp.head, &temp.key , &temp.end ) ;list1.push_back( temp ) ;}}int  findLoc( int head ){int loc ;for ( int i = 0 ; i < Num ; i++ ){if ( list1[i].head == head ){loc = i ;return loc ;}}}void deal_ (){int loc = findLoc( head ) ;list2.push_back( list1[loc])  ; while ( list1[loc].end != -1 ){loc = findLoc ( list1[loc].end ) ;list2.push_back( list1[loc] );}sort ( list2.begin() , list2.end() ) ;for ( int i = 0 ; i < list2.size() -1 ; i++ ){list2[i].end = list2[i+1].head ;}list2[list2.size() -1].end = -1 ; }void showList(){if ( list2.size() == 0){  printf("0") ;  return ;}printf("%d %05d\n", list2.size() , list2[0].head) ;for ( vector<node>::iterator it = list2.begin() ; it != list2.end() ; it++ ){if ( it != list2.end() -1){printf( "%05d %d %05d\n", it->head , it->key , it->end ) ; }else{printf("%05d %d %d", it->head, it->key , it->end ) ;}}}int main ( void ){getInput() ;deal_() ;showList() ;return 0 ;}

second code : 在下面的这段代码中,对第一个运行超时的问题进行了修改, 使得在输入数据的时候,存放数据的数组下标与
对应的节点的 起始地址的值是相同的, 这个地方是典型的使用空间来换取时间的策略。

在这个地方需要注意的是,如果数组需要的空间很大的话,就应该将vector 等容器使用数组进行替换,不然会出错的。
下面的代码运行没有超时,再一次成功的通过的一个测试点。

对于最后的额这个测试点,挺同学说过,这个地方应该考虑到空链表的地方。
还有一名前辈告诉我说,这道题目的坑是 对应的输入数据中存在 节点 在进行链表的模拟之后是不属于头尾相接的链表的,
这种情况应该将该顶点从 list 中进行删除,使得最终得到的链表的顶点个数有所减少,这坑果然是坑。

不过空链表这种情况,我不是很明白输出格式中的格式应该是什么样子的,但是题目中的描述是这样的:
Input 的格式与 Output 的格式完全是相同的,空链表对应的是输入的数据就是空链表。
如果是整理之后,剔除不必要顶点之后的链表为空的话, 那么会于头顶点给出具体数值发生矛盾。

所以第三次提交的时候,打算在代码中添加这样的一句

if ( list1.size() == 0 ){printf("%d %05d", Num , head ) ;return ;} 

不对,这里我忘了将 list1从 vector 修改成为了 数组,所以这里的判断语句为 

if ( Num == 0 ){....}

将这段话添加到 showList2 方法的开头处。


second code : 24/25
/**first read in all the nums into the list then find the head elements , and select it from the list and insert it into the first place of another list2 , and select from the list1 the element which head = x .end*/#include <cstdio>#include <cstdlib>#include <vector>#include <algorithm>using namespace std ;#define Max 1001struct node{int head, end ,key ;bool operator < ( const node &b ) const{return key < b.key ;}} ;struct node list1[100000] ;int Num , head ;struct node list2[100000] ; int len = 0 ;void getInput2(){node temp ;int nextLoc ;scanf("%d%d", &Num , &head ) ; for ( int i = 0; i < Num ; i++ ){ scanf("%d%d%d", &temp.head , &temp.key , &temp.end) ;list1[temp.head] = temp ;}nextLoc = head ;while ( nextLoc != -1 ){list2[len++] = list1[nextLoc] ;nextLoc = list1[nextLoc].end ;}}void deal2_(){sort( list2 , list2+len ) ;    for ( int i = 0 ; i < len -1 ; i++ ){list2[i].end = list2[i+1].head ;}list2[len-1].end = -1 ;}void showList2( ){printf("%d %05d\n", len ,list2[0].head  ) ;for ( int i = 0 ; i < len-1 ; i++ ){printf("%05d %d %05d\n", list2[i].head , list2[i].key , list2[i].end ) ;}printf("%05d %d -1", list2[len-1].head , list2[len-1].key ) ;}int main ( void ){getInput2() ;deal2_() ;showList2() ; return 0 ;}


24 分已经进入瓶颈了, 对于最后一种情况,我分别测试了 list2(经过筛选之后的链表) 长度为 0  的数值 以及输入head 数值。
以及将接受的数据 ( 未经筛选的链表长度和头顶点的起始地址),其实这里最终要的一点就是,题中并没有说明,
当经过筛选之后的链表为空链表的时候,对应的头结点的起始地址应该如何表示。

最后测试一下, 0 00000 这种格式,以及 0 -1 这两种格式的,如果还没有通过的话, 这道题目只能作为错题备份了。

好吧,最后那种情况通过了....  

25 分,心得就是,程序这个东西,必须是需要自己动手去实现,自己动脑去想的,查看解题报告对一个人编程思维的提高并不是很好的,
暂时的可能是应付着AC出一道题目两道题目,但是,
一旦自己花费大量的时间去想一道题目的时候, 即便是最后没有得到正确的答案,但是,思考的过程绝对会使你收益终身的。

还有最后一点,作为时刻提醒自己的,就是无论最后的代码是否通过了,都要对其进行备份,毕竟是自己思考的结果,不能随随便便的丢弃。
自己写的东西,今后真的是很有参考价值的。 每一次的修改,每一次的思路生成的代码都是很有用的。

下面是通过的完整代码 ,thrid code 25/25:

/**first read in all the nums into the list then find the head elements , and select it from the list and insert it into the first place of another list2 , and select from the list1 the element which head = x .end*/#include <cstdio>#include <cstdlib>#include <vector>#include <algorithm>using namespace std ;#define Max 1001struct node{int head, end ,key ;bool operator < ( const node &b ) const{return key < b.key ;}} ;struct node list1[100000] ;int Num , head ;struct node list2[100000] ;int len = 0 ;void getInput2(){node temp ;int nextLoc ;scanf("%d%d", &Num , &head ) ;   if ( Num == 0 )    return ;  for ( int i = 0; i < Num ; i++ ){ scanf("%d%d%d", &temp.head , &temp.key , &temp.end) ;list1[temp.head] = temp ;}nextLoc = head ;while ( nextLoc != -1 ){list2[len++] = list1[nextLoc] ;nextLoc = list1[nextLoc].end ;}}void deal2_(){sort( list2 , list2+len ) ;    for ( int i = 0 ; i < len -1 ; i++ ){list2[i].end = list2[i+1].head ;}list2[len-1].end = -1 ;}void showList2( ){  if ( len == 0  )  {  printf("%d -1", len ) ;  return ;  } printf("%d %05d\n", len ,list2[0].head  ) ;for ( int i = 0 ; i < len-1 ; i++ ){printf("%05d %d %05d\n", list2[i].head , list2[i].key , list2[i].end ) ;}printf("%05d %d -1", list2[len-1].head , list2[len-1].key ) ;}int main ( void ){  getInput2() ;deal2_() ;  showList2() ; return 0 ;}


0 0
原创粉丝点击