题目描述:
给你一个 n 个整数的序列 a1,a2,…,an,一个 132 模式是对于一个子串 ai,aj,ak,满足 i < j < k 和 ai < ak < aj。设计一个算法来检查输入的这 n 个整数的序列中是否存在132模式。
n 会小于 20,000。
样例:
给你序列 nums = [1,2,3,4]
返回 False//没有132模式在这个序列中。
给你序列 nums = [3,1,4,2]
返回 True//存在132模式:[1,4,2]。
标签:
栈、数组
思路讲解:
首先这道题的最简单的方法就是直接暴力破解即三重循环然后判断 ai < ak < aj,这样不出意外都会超时,果然最后超时了,然后我又想了另外一种方法,由于 aj是中间的,我们需要在其左边找到一个比他小的数字,然后在他的右边找到一个比他小但是比他左边最小的数大的数,,首先我们找到aj左边的最小数,我们可以利用一个数组存储位置j左边最小的数,这样我们只需要O(n)的复杂度就能得到所有数字左边最小的数,下面就是关于找到aj右边小于他的最大数,这里一开始我是直接遍历的,结果还是超时,思来想去超时的原因就是上面求有条件的最大值时,会重复判断很多次,导致时间不够,思来想去,结合标签的提示想到了运用栈来进行操作,并且是从结尾开始,每一个我们都将栈顶元素跟nums[j]进行比较,如果其大于栈顶,说明下面有可能还有小于他的数,但比刚才的数要大,因为我们要找到其右边小于他的最大的数,直到我们找到了,然后将其与位置j的p[j]比较,如果其大于它,那么就找到了返回true,不然 就将nums[j]添加进栈中,一直这样进行下去。
代码详解:
class Solution {
public:
/*
* @param nums: a list of n integers
* @return: true if there is a 132 pattern or false
*/
bool find132pattern(vector<int> &nums) {
// write your code here
int len=nums.size();
if(len<3){
return false;
}
stack<int>bolt;//存储位置j后最大的数
int *p=new int[len];//用来存储位置j前最小的数
int min=INT_MAX;
for(int i=0;i<len;i++)
{
if(nums[i]<min){
min=nums[i];
}
p[i]=min;
}
for(int i=len-1;i>=0;i--)
{
if(nums[i]>p[i]){
int max=INT_MIN;//存储小于其最大的数
while(!bolt.empty()&&nums[i]>bolt.top()){
max=bolt.top();
bolt.pop();
}
if(max>p[i]){
return true;
}
}
bolt.push(nums[i]);
}
return false;
}
};
如果你们想了解其他的解法,请访问下面的页面:https://www.cnblogs.com/grandyang/p/6081984.html