int数组,找小于右边所有数,大于左边所有数的数

一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

老早就想把这道题目写了,一直没写;N天不碰算法,思维完全钝了。

网络上的解法思路(见附),都是一直的。那如果再说一模一样的就没太大意思,除了记录题目和增加网络冗余度之外;

其实这里说的和网络大部分也是一样的,但是,解释稍微转变,希望让你这透彻的看懂它。

经一番琢磨,题目很网上的解释包含了一个很简单的思想,“单调栈”,哈哈,是不是很熟悉呢?

如果想不起来,就回去看看其他博文中的题目吧:单调栈:柱形统计图中最大面积(POJ 2559) 谁看得最大 (使用了单调栈的思想)

好了这里,当你理解了单调栈了,可以开始解题了;

7, 10, 2, 6, 19, 22, 32

如果只遍历一遍,我们很容易可以知道它是否比它前面的所有数要大(记录其前面遍历的最大元素),例如,这时遍历到19了,之前先记录前面最大的(这是可以做到的),为10。因为19>10 所有19符合其中大于等于其前面所有元素的条件。这时同时也记录最大元素为19,接着检测下一个元素。

好,这里我们完成了检测“左边的数都小于等于它”的条件,麻烦就在于“右边的数都大于等于它”;这时候“单调栈”的思想就可以很好的解决这个问题。因为它保证了每次压进栈里的元素是单调递增的。如果不是递增,把之前栈内的元素出栈(这些元素已经不符合“右边的数都大于等于它”了),保持单调栈的特性。

所有把符合上述的元素放在单调栈中就OK了。

OK,简单吧。自认为比一些网络上了各种抄的复杂解释来得简单,当然也有人会认为其他的要简单,whatever,反正我们都理解了。

 1 void func37(int a[], int n)
 2 {
 3     assert(a && n>0);
 4 
 5     int pre_max = -INT_MAX;   //可使用栈的特性剔除这个变量
 6     int i;
 7     stack<int> st;
 8 
 9     for (i=0; i<n; i++)
10     {
11         if (a[i] >= pre_max)
12         {
13             pre_max =  a[i];            
14 
15             while(!st.empty() && a[st.top()] > a[i]) //保存栈的特性
16             {
17                 st.pop();
18             }
19 
20             st.push(i);
21         }
22         else
23         {
24             while(!st.empty() && a[st.top()] > a[i]) //保存栈的特性
25             {
26                 st.pop();
27             }
28             continue;
29         }        
30     }
31 
32     if (st.empty())
33     {
34         cout<<"no one is appropriated"<<endl;
35         return;
36     }
37     while(!st.empty())
38     {
39         cout<<a[st.top()]<<" ";
40         st.pop();
41     }    
42     cout<<endl;
43 }

 

附:

最原始的方法是检查每一个数 array[i] ,看是否左边的数都小于等于它,右边的数都大于等于它。这样做的话,要找出所有这样的数,时间复杂度为O(N^2)。

其实可以有更简单的方法,我们使用额外数组,比如rightMin[],来帮我们记录原始数组array[i]右边(包括自己)的最小值。假如原始数组为: array[] = {7, 10, 2, 6, 19, 22, 32}, 那么rightMin[] = {2, 2, 2, 6, 19, 22, 32}. 也就是说,7右边的最小值为2, 2右边的最小值也是2。

有了这样一个额外数组,当我们从头开始遍历原始数组时,我们保存一个当前最大值 max, 如果当前最大值刚好等于rightMin[i], 那么这个最大值一定满足条件。还是刚才的例子。

第一个值是7,最大值也是7,因为7 不等于 2, 继续,

第二个值是10,最大值变成了10,但是10也不等于2,继续,

第三个值是2,最大值是10,但是10也不等于2,继续,

第四个值是6,最大值是10,但是10不等于6,继续,

第五个值是19,最大值变成了19,而且19也等于当前rightMin[4] = 19, 所以,满足条件。

如此继续下去,后面的几个都满足。

 

posted @ 2013-05-20 19:07  legendmaner  阅读(1139)  评论(0编辑  收藏  举报