pat1052

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 00001
11111 100 -1
00001 0 22222
33333 100000 11111
12345 -1 33333
22222 1000 12345
Sample Output:
5 12345
12345 -1 00001
00001 0 11111
11111 100 22222
22222 1000 33333
33333 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 1001

struct 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 1001

struct 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 1001

struct 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 ;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章