1. 程式人生 > 其它 >單調棧結構(進階) 牛客網

單調棧結構(進階) 牛客網

技術標籤:程式設計師面試指南188

題目描述
給定一個不含有重複值的陣列 arr,找到每一個 i 位置左邊和右邊離 i 位置最近且值比 arr[i] 小的位置。返回所有位置相應的資訊。

輸入描述:
第一行輸入一個數字 n,表示陣列 arr 的長度。

以下一行輸出 n個數字,表示陣列的值。
輸出描述:
輸出n行,每行兩個數字 L 和 R,如果不存在,則值為-1,下標從0開始。
示例1
輸入
複製
7
3 4 1 5 6 2 7
輸出
複製
-1 2
0 2
-1 -1
2 5
3 5
2 -1
5 -1

思路:首先構成一個單調棧,放入元素是有3種情況:
(1)棧為空,直接放入
(2)棧不為空,且棧頂元素大於當前放入元素,彈出棧頂元素,繼續判斷屬於那種情況

(3)棧不為空,且棧頂元素小於當前放入元素,直接放入

將所有元素放入後,此時棧是一個從上到下逐漸遞減的排列,依次彈出即可。具體細節見程式碼。

關於,這道題的進階,放入元素中出現了重複元素,此時單調棧中存放的不再是單一的元素,而是一個list連結串列,導論情況大致相同,只是,多一種等於棧頂元素時,放入當前棧頂連結串列。細節見程式碼,主要難點時stack,與list的配合使用。

 #include<stdio.h>
 #include<stack>
 using namespace std;
 
 
 stack<int> stack_1;
 int arr[
1000007]; int left[1000007]; int right[1000007]; int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&arr[i]); for(int i=0;i<n;i++) { while( !stack_1.empty() && arr[ stack_1.top() ]>arr[i] ) { int x=stack_1.top(); stack_1.
pop(); right[x]=i; left[x]= stack_1.empty()? -1:stack_1.top(); } stack_1.push(i); } //現在是一個單調棧,需要將棧中的元素清除 while( !stack_1.empty() ) { int x=stack_1.top(); stack_1.pop(); right[x]=-1; left[x]=stack_1.empty() ? -1:stack_1.top(); } for(int i=0;i<n;i++) printf("%d %d\n",left[i],right[i]); return 0; }

題目描述
給定一個可能含有重複值的陣列 arr,找到每一個 i 位置左邊和右邊離 i 位置最近且值比 arr[i] 小的位置。返回所有位置相應的資訊。
輸入描述:
第一行輸入一個數字 n,表示陣列 arr 的長度。
以下一行輸入 n 個數字,表示陣列的值
輸出描述:
輸出n行,每行兩個數字 L 和 R,如果不存在,則值為 -1,下標從 0 開始。
示例1
輸入
複製
7
3 4 1 5 6 2 7
輸出
複製
-1 2
0 2
-1 -1
2 5
3 5
2 -1
5 -1

 #include<stdio.h>
 #include<stack>
 #include<list>
 using namespace std;
 
 stack< list<int> > stack_1;
 list<int>::iterator it;
  int arr[1000007];
 int left[1000007];
 int right[1000007];
 
 int main()
 {
 	int n;
 	scanf("%d",&n);
 	for(int i=0;i<n;i++)
 	  scanf("%d",&arr[i]);
 	
 	for(int i=0;i<n;i++)
	 {
//	 	it=stack_1.top().begin();
	 	while( !stack_1.empty() && arr[ *(stack_1.top().begin() ) ]>arr[i]  )
		 {
		 	 
		 	list<int> mylist;
		 	for( it=stack_1.top().begin(); it!=stack_1.top().end()  ; it++ )
			 	mylist.push_back( *it );//賦值把stack_1.top賦值到mylist中 
		 	stack_1.pop();
		 	for( it= mylist.begin() ; it!=mylist.end() ; it++ )
			 {
			 	right[ *it ]=i;
			 	left[ *it ]= stack_1.empty() ? -1 : *( --stack_1.top().end() );
			 } 
		 }
		 
		 if( !stack_1.empty() && arr[ *(stack_1.top().begin() ) ]==arr[i]  )//當前放入元素和隊首相等 
		 {
		 	stack_1.top().push_back( i );
		 }
		 else
		 {
		 	list<int> mylist2;
		 	mylist2.push_back( i );
		 	stack_1.push( mylist2 );
		 }
	 }
	 
	 //此時是一個單調棧結構
	 while( !stack_1.empty() )
	 {
	 	list<int> mylist3;
	 	for( it=stack_1.top().begin() ; it!=stack_1.top().end() ; it++ )
		 	mylist3.push_back( *it );
	 	stack_1.pop();
	 	for( it=mylist3.begin() ; it!=mylist3.end() ; it++  )
		 {
		 	right[ *it ]=-1;
		 	left[ *it ]= stack_1.empty() ? -1 : *( --stack_1.top().end() );
	 		
		 }
	 	
	 } 
 	
 	for(int i=0;i<n;i++)
	   printf("%d %d\n",left[i],right[i]); 
 	
 	
 
 	return 0;
 }